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