Set

136 阅读4分钟

1. Set()构造函数

【概念】 Set 是 ES6 新增的数据结构,它类似于数组,但成员的值是唯一的无重复值

  • Set 本身是一个构造函数,需要通过 new 的方式创建实例,去生成 Set 数据结构
let set = new Set();

【参数】

  • Set 添加值可以通过传参的方式传值,也可以通过调用原型上的 add 方法

  • 参数是具备 iterator 的接口的数据结构,包括数组类数组

【特点】

  • 值唯一,相等的值只会保留一个
  • 类似于数组的结构
console.log(new Set([1, 2, 7, 7, 7]));

下面的例子:

var set = new Set(
  [0, -0, undefined, undefined, null, null, 5, '5', true, 1, NaN, NaN, {}, {},[], [] 
  ])

console.log(set)

/*
	数字 5 和字符串 '5' 不相等
 	空对象和空对象不相等
 	空数组和空数组不相等
*/

image.png

由此例子可以得出 Set中几个特殊值:

  • +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复

  • undefinedundefined 恒等的,所以不重复

  • NaN 与 NaN 是不恒等的,但是在 Set 认为NaNNaN相等

1.1 操作当前数据结构的方法

1.add():添加

调用该方法返回的是 Set 结构本身, 当添加实例中已经存在的元素, set 不会进行处理添加

var set = new Set();


var x = {
        id: 1
    },
    y = {
        id: 2
    };
set.add(x).add(y);  // 添加值,返回的是Set结构本身,所以可以链式调用
set.add(x);	    // 两个 x 虽然都是对象,但是引用的地址值是一样的

// size 长度
console.log(set.size);
console.log(set);

2.delete():删除

删除元素本身, 返回布尔值, 代表删除与否

注意: 删除操作是实时的,具体看下面两段代码输出内容的差别

let set = new Set();

let x = {
    id: 1,
},
    y = {
        id: 2,
    };

set.add(x).add(y);
console.log(set.delete(y));
console.log(set.delete(y));
console.log(set);

let set = new Set();

let x = {
    id: 1,
},
    y = {
        id: 2,
    };

set.add(x).add(y);
console.log(set);
console.log(set.delete(y));

由此我们可以看出输出的 set 集合中的值不因为先进行删除还是后进行删除而变化

3.has():是否有某个值

表示是否有某个值,返回布尔值,代表删除与否

let set = new Set();

let x = {
    id: 1,
},
    y = {
        id: 2,
    };

set.add(x).add(y);
console.log(set.has(x)); 	// true

4.clear():清除

清除所有成员,没有返回值(返回 undefined),与 delete一样,操作是实时的

以下两段代码:

let set = new Set();

let x = {
    id: 1,
},
    y = {
        id: 2,
    };
console.log(set.clear());
console.log(set);

let set = new Set();

let x = {
    id: 1,
},
    y = {
        id: 2,
    };

console.log(set);
console.log(set.clear());

1.2 迭代的方法

1.keys()、values()、entries()

  • keys() :返回键 的遍历器。

  • values() :返回键 的遍历器。

  • entries() :返回键值 的遍历器。

【特点】

  1. set没有键名 只有值,所以返回的 keys 和 values 是一样的,都是值
  • 遍历 set本身,for of本质上是调用 Set.prototype.values

  • Set.prototype[Symbol.iterator] === Set.prototype.values;

let set = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g']);

console.log(set.keys());
console.log(set.values());
console.log(set.entries());

// set 没有键名 只有值,所以返回的keys和values是一样的,都是值
for (let i of set.keys()) {
    console.log(i); // 返回一个键名的迭代器
}
for (let i of set.values()) {
    console.log(i); // 返回一个键值的迭代器
}
for (let i of set.entries()) {
    console.log(i); // 返回一个键值对的迭代器
}

// 遍历 set 本身
// for of 本质上是调用 Set.prototype.values
for (let i of set) {
    console.log(i)     // 输出 a  b c d e f g
}

2.forEach

使用回调函数遍历每个成员,本质同数组的 forEach类似

【参数】 分别对应:

  • 每个元素

  • 索引

  • 被遍历的数组

let set = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g']);

set.forEach((value, keys, arr) => {
    console.log(value, keys, arr)
})

2. Set 常见用法

1. 利用set进行数组去重

拓展运算符能够展开具有迭代器接口的数据结构

let set = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g']);

// 可以利用set进行数组去重
console.log([...set]);

/*
	通过 set 值的唯一性,将数组作为参数传入,再通过拓展运算符将梳理后的数组展开
*/

2. 结合map修改元素值

题目: 将传入数组中的元素成倍输出

思路:将 set 通过解构的方式变为数组,再去调用数组上的 map 方法

let set = new Set([1, 2, 3, 4, 5]);
console.log(set);

let set1 = new Set([...set].map((value) => value * 2));

console.log(set1);

3. 结合parseInt

var arr = [1, 2, 3, 4];
var arr1 = arr.map(parseInt); 
console.log(arr1);		// 输出  [1, NaN, NaN, NaN]

/* 
  这里parseInt会传入两个参数parseInt(item, index)
*/

// 相当于
var arr2 = arr.map((values, index) => console.log(values, index));
// 输出  1 0、2 1、3 2、4 3



let set = new Set([1, 2, 3, 4, 5, 6, 7]);
let set2 = new Set([
    [...set].map(parseInt)
])

3. 结合filter

let set = new Set([1, 2, 3, 4, 5, 6, 7]);
let set2 = new Set([...set].filter((x) => {
  return (x % 2) === 0
}));

console.log(set2);

3. 实现交集、并集、差集

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

// 并集
let union = new Set([...a, ...b]);
console.log(...[union]);

// 交集
let intersect = new Set([...a]).filter((x) => {
  return b.has(x)
});
console.log(intersect);

// 差集
let difference = new Set([...a]).filter((x) => {
  !b.has(x);
})
console.log(difference);

4. 映射出一个新的结构

let set = new Set([1, 2, 3]);

// 方式1 map
let set1 = new Set([...set].map(value => value * 2));

// 方式2 Array.from
let set2 = new Set(Array.from(set, value => value * 2))