JavaScript对象和数组是最常用的数据结构,充当数据集合。在ES6之前,开发人员的选择有限。但是有了ES6,我们有了两种新的灵活且易于使用的数据结构,Map和Set。
Set
Set是唯一(不同)元素的集合,其中每个元素可以是任何类型。Set也是元素的有序集合。这意味着元素的检索顺序将与插入顺序相同。
JavaScript 的set集合行为方式与数学集相同。
创建一个Set
const set = new Set();
console.log(set);
输出
Set(0) {}
初始化一个Set集合并创建
const fruteSet = new Set(['🍉', '🍎', '🍈', '🍏']);
console.log(fruteSet);
输出
Set(4) {"🍉", "🍎", "🍈", "🍏"}
设置方法-让我们做一些沙拉🥗!
Set具有向其添加元素、从中删除元素、检查其中是否存在元素以及完全清除它的方法。让我们通过做一些沙拉来看看它!
添加蔬菜
使用add(element)方法将元素添加到Set。
const saladSet = new Set();
saladSet.add('🍅');
saladSet.add('🥑');
saladSet.add('🥕');
saladSet.add('🥒');
console.log(saladSet);
好了,我们已经添加了蔬菜。到目前为止的输出
Set(4) {"🍅", "🥑", "🥕", "🥒"}
再加一根黄瓜——我们可以吗?
我喜欢黄瓜!再加一个怎么样?我可以吗?哦,不,我不能。set是唯一的元素的集合。
saladSet.add('🥒');
console.log(saladSet);
输出仍然和以前一样,没有任何东西添加到saladSet中
Set(4) {"🍅", "🥑", "🥕", "🥒"}
它有胡萝卜(🥕)或西兰花(🥦)吗?
使用has(element)方法搜索Set中的元素。
console.log('沙拉里有胡萝卜吗?', saladSet.has('🥕'));
console.log('沙拉里有西兰花吗??', saladSet.has('🥦'));
使用delete(element)方法从Set中删除元素。
saladSet.delete('🥑');
console.log('我不喜欢🥑,从沙拉里拿出来:', saladSet);
现在我们的沙拉套餐是,
我不喜欢🥑,从沙拉里拿出来: Set(3) {"🍅", "🥕", "🥒"}
让我们清理一下,吃完沙拉!
使用clear()方法从Set中删除所有元素
saladSet.clear();
console.log('Finished it:', saladSet);
输出
Finished it: Set(0) {}
使用Set迭代
Set有一个名为values()的方法,它返回一个SetIterator以获取所有值。
const houseNos = new Set([360, 567, 101]);
console.log(houseNos.values());
输出
SetIterator {360, 567, 101}
我们可以在这上面使用foreach或for-of循环来检索值。
有趣的事实:JavaScript强调使Set与Map兼容。这就是为什么我们找到了两个Set方法,keys()和entries(),就像Map一样。
由于Set没有键,keys()方法返回一个SetIterator来检索值。
console.log(houseNos.keys());
输出
SetIterator {360, 567, 101}
现在尝试Map的entries()它返回迭代器以检索键值对。Set没有键。因此,entries()方法返回一个SetIterator来检索 值-值对。
console.log(houseNos.entries());
输出
SetIterator {360 => 360, 567 => 567, 101 => 101}
让我们枚举
我们可以使用forEach和for-of循环枚举一个Set。
houseNos.forEach((value) => {
console.log(value);
});
输出
360
567
101
用for-of
for(const value of houseNos) {
console.log(value);
}
Set and object
Set可以有任何类型的元素,甚至是对象。
const person = { 'name': 'Alex', 'age': 32 };
const pSet = new Set();
pSet.add(person);
console.log(pSet);
输出
毫不奇怪。Set包含一个作为对象的元素。现在让我们更改对象的属性并再次将其添加到集合中。
person.name = 'Bob';
pSet.add(person);
console.log(pSet);
你觉得输出怎么样?两个person的对象还是一个?这是输出,
Set是唯一元素的集合。通过更改对象的属性,我们没有更改对象本身。因此Set不允许重复元素。
Set and Array
数组,如Set,允许向其添加和删除元素。但是Set与数组不同,它并不意味着替换数组。
数组和Set之间的主要区别是,数组允许重复元素,其中Set用于不同的元素。一些Set操作(delete)也比数组操作(shift, splice)更快。
Set数据结构不是数组的替代品。与数组一起设置可以解决有趣的问题。
将Set转换为数组
在许多情况下,您可能希望将Set转换为数组。事实上,这很容易!
const arr = [...houseNos];
console.log(arr);
输出
使用Set从数组中获取唯一值
Set数据结构最常见的用法是从数组中获取唯一值。
const mixedFruit = ['🍉', '🍎', '🍉', '🍈', '🍏', '🍎', '🍈',];
const mixedFruitSet = new Set(mixedFruit);
console.log(mixedFruitSet);
输出
Set(4) {"🍉", "🍎", "🍈", "🍏"}
Set 操作
Set集合和数组一起执行基本的集合操作非常容易,如union(并集)、intersection(交集)、diference(集差)、superset(超集)、subset(子集)等。让我们用这两个集合来执行这些操作
const first = new Set([1, 2, 3]);
const second = new Set([3, 4, 5]);
Union
集合A和B的并集,表示为A ∪ B,是作为A或B或两者的成员的所有项的集合。例如。{1,2,3}和{3,4,5}的并集是集合{1,2,3,4,5}。
const union = new Set([...first, ...second]);
console.log('Union:', union);
输出
Union: Set(5) {1, 2, 3, 4, 5}
Intersection
集合A和B的交集,表示为A ∩ B,是同时属于A和B的所有对象的集合。例如,{1,2,3}和{3,4,5}的交集是集合{3}。
const intersection = new Set([...first].filter(elem => second.has(elem)));
console.log('Intersection:', intersection);
输出
Intersection: Set(1) {3}
Difference
U和A的集差,表示U \ A,是U中所有不是A成员的成员的集合。集差{1,2,3}{3,4,5}为{1,2},反之,集差{3,4,5}{1,2,3}为{4,5}。
const difference = new Set([...first].filter(elem => !second.has(elem)));
输出
Difference: Set(2) {1, 2}
Superset
如果A的所有元素也是B的元素,则集合A是集合B的子集;B是A的超集。
const isSuperset = (set, subset) => {
for (let elem of subset) {
if (!set.has(elem)) {
return false;
}
}
return true;
}
console.log('Is Superset?', isSuperset(first, second));
输出
Is Superset? false