1.Map
Map 是一个带键的数据项的集合,就像一个 Object
一样。 但是它们最大的差别是 Map
允许任何类型的键(key)。
它的方法和属性如下:
new Map()
—— 创建 map。map.set(key, value)
—— 根据键存储值。map.get(key)
—— 根据键来返回值,如果map
中不存在对应的key
,则返回undefined
。map.has(key)
—— 如果key
存在则返回true
,否则返回false
。map.delete(key)
—— 删除指定键的值。map.clear()
—— 清空 map。map.size
—— 返回当前元素个数。
let map = new Map();
map.set('1', 'str1'); // 字符串键
map.set(1, 'num1'); // 数字键
map.set(true, 'bool1'); // 布尔值键
// 还记得普通的 Object 吗? 它会将键转化为字符串
// Map 则会保留键的类型,所以下面这两个结果不同:
alert( map.get(1) ); // 'num1'
alert( map.get('1') ); // 'str1'
alert( map.size ); // 3
Map 还可以使用对象作为键。
let john = { name: "John" };
// 存储每个用户的来访次数
let visitsCountMap = new Map();
// john 是 Map 中的键
visitsCountMap.set(john, 123);
alert( visitsCountMap.get(john) ); // 123
在 Object
中,我们则无法使用对象作为键。在 Object
中使用字符串作为键是可以的,但我们无法使用另一个 Object
作为 Object
中的键。
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
// 遍历所有的键(vegetables)
for (let vegetable of recipeMap.keys()) {
alert(vegetable); // cucumber, tomatoes, onion
}
// 遍历所有的值(amounts)
for (let amount of recipeMap.values()) {
alert(amount); // 500, 350, 50
}
// 遍历所有的实体 [key, value]
for (let entry of recipeMap) { // 与 recipeMap.entries() 相同
alert(entry); // cucumber,500 (and so on)
}
Map 迭代
如果要在 map
里使用循环,可以使用以下三个方法:
map.keys()
—— 遍历并返回一个包含所有键的可迭代对象,map.values()
—— 遍历并返回一个包含所有值的可迭代对象,map.entries()
—— 遍历并返回一个包含所有实体[key, value]
的可迭代对象,for..of
在默认情况下使用的就是这个
2.Set
// 定义一个空的set集合
let s = new Set()
console.log(s)
// 可以去重
let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿'])
console.log(s2) //{'大事儿','小事儿','好事儿','坏事儿'}
// 元素个数
console.log(s2.size) //4
// 添加
s2.add('喜事儿')
// 删除
s2.delete('坏事儿')
// has 检测
s2.has('好事儿') //true
// 清空
s2.clear()
console.log(s2)
// 集合是iterat的一个接口,所以可以用for of 来遍历数据
for (let v of s2){
console.log(v)
}
- Set的应用
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1]
// 1.数组去重,可以用数组的扩展运算符把他变成数组
// let result = [...new Set(arr)]
// console.log(result)
效果相等的去重: console.log(Array.from(new Set(arr)))
// 交集
let arr2 = [4, 5, 6, 5, 6]
// let result = [...new set(arr).filter(item =>new set(arr2).has(item))]
// console.log(result)
// 并集
let union = [...new set([...arr, ...arr2])]
// 差集,谁是主题影响结果,是交集的取反
let diff = [...new set(arr)].filter(item => !(new set(arr2).has(item)))
console.log(diff)
补充数组去重:reduce
function unique(arr){
return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
数组对象去重:
let log = console.log.bind(console);
let person = [
{id: 0, name: "小明"},
{id: 1, name: "小张"},
{id: 2, name: "小李"},
{id: 3, name: "小孙"},
{id: 1, name: "小周"},
{id: 2, name: "小陈"},
];
let obj = {};//有助于增加遍历效率
person = person.reduce((cur,next) => {
obj[next.id] ? "" : obj[next.id] = true && cur.push(next);
return cur;
},[]) //设置cur默认类型为数组,并且初始值为空的数组
log(person)
Map
中用于迭代的方法在 Set
中也同样支持:
set.keys()
—— 遍历并返回一个包含所有值的可迭代对象,set.values()
—— 与set.keys()
作用相同,这是为了兼容Map
,set.entries()
—— 遍历并返回一个包含所有的实体[value, value]
的可迭代对象,它的存在也是为了兼容Map
。
总结
Map
—— 是一个带键的数据项的集合。
方法和属性如下:
new Map([iterable])
—— 创建 map,可选择带有[key,value]
对的iterable
(例如数组)来进行初始化。map.set(key, value)
—— 根据键存储值,返回 map 自身。map.get(key)
—— 根据键来返回值,如果map
中不存在对应的key
,则返回undefined
。map.has(key)
—— 如果key
存在则返回true
,否则返回false
。map.delete(key)
—— 删除指定键对应的值,如果在调用时key
存在,则返回true
,否则返回false
。map.clear()
—— 清空 map 。map.size
—— 返回当前元素个数。
与普通对象 Object
的不同点:
- 任何键、对象都可以作为键。
- 有其他的便捷方法,如
size
属性。
Set
—— 是一组唯一值的集合。
方法和属性:
new Set([iterable])
—— 创建 set,可选择带有iterable
(例如数组)来进行初始化。set.add(value)
—— 添加一个值(如果value
存在则不做任何修改),返回 set 本身。set.delete(value)
—— 删除值,如果value
在这个方法调用的时候存在则返回true
,否则返回false
。set.has(value)
—— 如果value
在 set 中,返回true
,否则返回false
。set.clear()
—— 清空 set。set.size
—— 元素的个数。
在 Map
和 Set
中迭代总是按照值插入的顺序进行的,所以我们不能说这些集合是无序的,但是我们不能对元素进行重新排序,也不能直接按其编号来获取元素。
例子1:
1.去重
定义 arr 为一个数组。
创建一个函数 unique(arr),该函数返回一个由 arr 中所有唯一元素所组成的数组。
结果:
function unique(arr) {
/* 你的代码 */
return Array.from(new Set(arr));
}
let values = ["Hare", "Krishna", "Hare", "Krishna",
"Krishna", "Krishna", "Hare", "Hare", ":-O"
];
alert( unique(values) ); // Hare, Krishna, :-O
例子2:
2.过滤字谜
Anagrams 是具有相同数量相同字母但是顺序不同的单词。
例如:
nap - pan
ear - are - era
cheaters - hectares - teachers
写一个函数 aclean(arr),它返回被清除了字谜(anagrams)的数组。
结果:
function aclean(arr) {
let map = new Map();
for (let word of arr) {
// 将单词 split 成字母,对字母进行排序,之后再 join 回来
let sorted = word.toLowerCase().split('').sort().join(''); // (*)
map.set(sorted, word);
}
return Array.from(map.values());
}
let arr = ["nap", "teachers", "cheaters", "PAN", "ear", "era", "hectares"];
alert( aclean(arr) );
例子3:
迭代键
重要程度: 5
我们期望使用 map.keys() 得到一个数组,然后使用例如 .push 等特定的方法对其进行处理。
但是运行不了:
let map = new Map();
map.set("name", "John");
let keys = map.keys();
// Error: keys.push is not a function
keys.push("more");
这是因为 map.keys() 返回的是可迭代对象而非数组。
我们可以使用方法 Array.from 来将它转换为数组:
let map = new Map();
map.set("name", "John");
let keys = Array.from(map.keys());
keys.push("more");
alert(keys); // name, more