es6的Map映射、Set集合总结

  • Post author:
  • Post category:其他


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)

    }
  1. 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

参考:

Map and Set(映射和集合)



版权声明:本文为WJLcomeon原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。