ES 6のセット(転載)

6259 ワード

セット
ES 6は、新しいデータ構造Setを提供する.配列に似ていますが、メンバーの値は全部唯一で、重複した値はありません.
Set自体はSetデータ構造を生成するためのコンストラクターである.
const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
  console.log(i);
}
// 2 3 5 4
上のコードはadd法によりSet構造にメンバーを追加したが、Set構造は重複した値を追加しないことを示した.
Set関数は、パラメータとして1つの配列(または、iterableインターフェースを有する他のデータ構造)を受け入れ、初期化することができる.
//   
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]

//   
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5

//   
function divs () {
  return [...document.querySelectorAll('div')];
}

const set = new Set(divs());
set.size // 56

//    
divs().forEach(div => set.add(div));
set.size // 56
上のコードでは、例1と例2はパラメータとしてSet関数受容配列であり、例3は同様の配列を受け入れるオブジェクトである.
上のコードでは、配列繰返しメンバを除去する方法も示している.
//          
[...new Set(array)]
Setに値を入れるとタイプ変換が発生しないので、5と5は2つの異なる値です.Set内部では、2つの値が異なるかどうかを判断し、使用するアルゴリズムを「Same-value equality」と呼び、精確な等しい演算子(===)に類似しています.主な違いはNaNが自身に等しく、精確なイコール演算子はNaNが自身に等しくないと考えられます.
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
上のコードはSetのインスタンスに二つのNaNを追加しましたが、一つしか追加できません.これはSet内部で二つのNaNが等しいことを示している.
また、2つのオブジェクトは常に同じではない.
let set = new Set();

set.add({});
set.size // 1

set.add({});
set.size // 2
上のコードは、2つの空のオブジェクトが等しくないため、それらは2つの値として扱われることを示しています.
Setのインスタンスの属性と方法
Set構造の例は以下のような属性がある.
Set.prototype.constructor:    ,    Set  。
Set.prototype.size:  Set       。
Setの例の方法は、2つの大きなクラスに分けられている.操作方法(データを操作するための)と、メンバを巡回するためのエルゴード方法.まず四つの操作方法を紹介します.
add(value):     ,   Set     。
delete(value):     ,       ,        。
has(value):       ,       Set   。
clear():      ,     。
これらの属性および方法の例は以下の通りである.
s.add(1).add(2).add(2);
//   2      

s.size // 2

s.has(1) // true
s.has(2) // true
s.has(3) // false

s.delete(2);
s.has(2) // false
以下は比較です.一つのキーの上にObject構造とSet構造の書き方が違っています.
//      
const properties = {
  'width': 1,
  'height': 1
};

if (properties[someName]) {
  // do something
}

// Set   
const properties = new Set();

properties.add('width');
properties.add('height');

if (properties.has(someName)) {
  // do something
}
Aray.from法はSet構造を配列に変えることができる.
const items = new Set([1, 2, 3, 4, 5]);
const array = Array.from(items);
これは配列繰返しメンバを除去する別の方法を提供する.
function dedupe(array) {
  return Array.from(new Set(array));
}

dedupe([1, 1, 2, 3]) // [1, 2, 3]
巡回操作
Set構造の例は、メンバーを巡回するために使用できる4つのエルゴード法である.
keys():        
values():        
entries():         
forEach():            
特に指摘したいのは、Setの巡回順序は挿入順序である.この特性は、Setを使用してコールバック関数のリストを保存するなど、非常に有用な場合があります.
(1)keys()、values()、entries()
keys方法、values方法、entries方法は全てエルゴードオブジェクトです.Setはキーの名前がないので、キーの値(またはキーの名前とキーの値が同じ値)しかないので、keysの方法とvaluesの方法は完全に一致しています.操作を巡回する
Set構造の例は、メンバーを巡回するために使用できる4つのエルゴード法である.
  • keys():キーパッドに戻るエルゴード
  • values():キー値を返すエルゴード
  • entries():キーパッドペアに戻るエルゴード
  • forEach():各メンバ
  • を巡回するために、コールバック関数を使用する.
    特に指摘されたいのは、Setのエルゴード順序は挿入順序である.この特性は、Setを使用してコールバック関数のリストを保存するなど、非常に有用な場合があります.
    (1)keys()values()entries()keys方法、values方法、entries方法で戻ってくるのは、エルゴードオブジェクトです.Set構造にはキー名がなく、キー値(またはキー名とキーパッド値が同じ値)しかないので、keys方法とvalues方法の動作は完全に一致しています.
    let set = new Set(['red', 'green', 'blue']);
    
    for (let item of set.keys()) {
      console.log(item);
    }
    // red
    // green
    // blue
    
    for (let item of set.values()) {
      console.log(item);
    }
    // red
    // green
    // blue
    
    for (let item of set.entries()) {
      console.log(item);
    }
    // ["red", "red"]
    // ["green", "green"]
    // ["blue", "blue"]
    
    上のコードの中で、entriesメソッドは、キーとキーの値を含むエルゴードを返します.だから、各配列を出力します.その二つのメンバーは完全に同じです.
    Set構造の実例はデフォルトでは巡回可能で、デフォルトのエルゴード生成関数はそのvalues方法です.
    Set.prototype[Symbol.iterator] === Set.prototype.values
    // true
    
    これは、values方法を省略してfor...ofサイクルをSetを巡回することができるという意味です.
    let set = new Set(['red', 'green', 'blue']);
    
    for (let x of set) {
      console.log(x);
    }
    // red
    // green
    // blue
    
    (2)forEach()
    Set構造の例は、配列と同じであり、各メンバに対して何らかの動作を実行するためのforEach方法もあり、戻り値がない.
    set = new Set([1, 4, 9]);
    set.forEach((value, key) => console.log(key + ' : ' + value))
    // 1 : 1
    // 4 : 4
    // 9 : 9
    
    上のコードによると、forEachメソッドのパラメータは処理関数です.この関数のパラメータは配列のforEachと一致しています.順番にキー、キー、セット自体です.ここで注意したいのですが、Set構造のキーの名前はキーの値ですので、最初のパラメータと第二のパラメータの値はいつまでも同じです.
    さらに,forEach法には,結合処理関数内部のthisオブジェクトを示す第二パラメータがあり得る.
    (3)遍歴の適用
    拡張演算子(...)の内部はfor...ofループを使用していますので、Set構造にも使用できます.
    let set = new Set(['red', 'green', 'blue']);
    let arr = [...set];
    // ['red', 'green', 'blue']
    
    拡張演算子とSet構造を組み合わせると、配列の重複したメンバが除去されます.
    let arr = [3, 5, 2, 2, 5, 5];
    let unique = [...new Set(arr)];
    // [3, 5, 2]
    
    また,配列のmapとfilter法は,Setに間接的に用いることもできた.
    let set = new Set([1, 2, 3]);
    set = new Set([...set].map(x => x * 2));
    //   Set  :{2, 4, 6}
    
    let set = new Set([1, 2, 3, 4, 5]);
    set = new Set([...set].filter(x => (x % 2) == 0));
    //   Set  :{2, 4}
    
    したがって、Setを使用すると、統合、インターリーブ、および差分セット(Difference)を容易に実現することができる.
    let a = new Set([1, 2, 3]);
    let b = new Set([4, 3, 2]);
    
    //   
    let union = new Set([...a, ...b]);
    // Set {1, 2, 3, 4}
    
    //   
    let intersect = new Set([...a].filter(x => b.has(x)));
    // set {2, 3}
    
    //   
    let difference = new Set([...a].filter(x => !b.has(x)));
    // Set {1}
    
    エルゴード操作において、元のSet構造を同期させたいなら、現在は直接的な方法はないが、二つの方法があります.一つは元のSet構造を利用して新しい構造をマッピングし、元のSet構造に値を付与することである.もう一つはAray.from法を利用することです.
    //    
    let set = new Set([1, 2, 3]);
    set = new Set([...set].map(val => val * 2));
    // set   2, 4, 6
    
    //    
    let set = new Set([1, 2, 3]);
    set = new Set(Array.from(set, val => val * 2));
    // set   2, 4, 6
    
    上のコードは2つの方法を提供し、直接エルゴード動作で元のSet構造を変更します.