在ES6中,给定一个Map,如何访问一对值,哪个顺序不重要?
如果这是数组,我会这样做:
let arr = ["a", "b", "c", "d"];
for (let i=0; i < arr.length; i++)
for (let j=i+1; j<arr.length; j++)
console.log(`${arr[i]},${arr[j]}`);
使用地图,我很难找到一种方法,以高效和优雅的方式做类似的事情。迭代器看起来像他们会这样做,但我假设他们的行为类似于C ++标准库迭代器,其中迭代器可以克隆到独立的迭代器中。
我提出的最好的是:
var map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);
for (let key of map.keys()) {
let log_away = false;
for (let other_key of map.keys()) {
if (log_away)
console.log(`${map.get(key)},${map.get(other_key)}`);
else
log_away = (key === other_key);
}
这是相当简洁的,但不管是否使用,必须访问所有对,都难以实现。更糟糕的是,如果要尝试将其调整为包含大型对象的Set,则最后的键的比较必须是值的比较,这可能非常昂贵。
答案 0 :(得分:6)
您可以调用values()
方法,然后在结果上调用Array.from()
以获取所有值的数组。然后你可以像对数组那样做。
const map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]])
const values = Array.from(map.values())
for (let i = 0; i < values.length; i++)
for (let j = i + 1; j < values.length; j++)
console.log(`${values[i]},${values[j]}`)
&#13;
答案 1 :(得分:2)
为混音添加一个循环选项(不是更好,只是替代方案):使用rest运算符始终循环其余条目。
let map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);
let arr = [...map.values()] ,v;
while(arr.length > 1){
[v,...arr] =arr;
arr.forEach(v2 => console.log([v,v2].join(',')));
}
&#13;
或在递归函数(变量)中执行相同操作以获取对数组:
let map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);
const fn = ([v,...a]) => v ? [...a.map(v2=>[v,v2].join()),...fn(a)] : [];
console.log(fn(map.values()));
&#13;
答案 2 :(得分:1)
您可以结合使用Array.from
,map.values()
和some
来创建此ES6解决方案:
var map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);
Array.from(map.values()).forEach( ([key1], i, a) =>
a.some( ([key2], j) => i !== j ? console.log(key2, key1) : true )
);
这使用console.log
不返回值的事实,因此必须注意在更实际的应用程序中重用它。因此,在数组中收集对可能更有用,然后可以将其用于以后的处理:
注意:使用点差运算符当然是Array.from
的替代选择:
var map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);
var pairs = [...map.values()].reduce( (acc, [key1], i, a) =>
(a.some( ([key2], j) => i === j || !acc.push([key2, key1]) ), acc), []
);
console.log(pairs);