jam*_*slk 135 javascript set ecmascript-6
有没有一种简单的方法将ES6地图合并在一起(比如Object.assign)?虽然我们在这,但ES6套装(如Array.concat)?
Ori*_*iol 224
套装:
var merged = new Set([...set1, ...set2, ...set3])
Run Code Online (Sandbox Code Playgroud)
对于地图:
var merged = new Map([...map1, ...map2, ...map3])
Run Code Online (Sandbox Code Playgroud)
请注意,如果多个地图具有相同的键,则合并地图的值将是具有该键的最后一个合并地图的值.
jam*_*slk 44
这是我使用生成器的解决方案:
对于地图:
let map1 = new Map(), map2 = new Map();
map1.set('a', 'foo');
map1.set('b', 'bar');
map2.set('b', 'baz');
map2.set('c', 'bazz');
let map3 = new Map(function*() { yield* map1; yield* map2; }());
console.log(Array.from(map3)); // Result: [ [ 'a', 'foo' ], [ 'b', 'baz' ], [ 'c', 'bazz' ] ]
Run Code Online (Sandbox Code Playgroud)
套装:
let set1 = new Set(['foo', 'bar']), set2 = new Set(['bar', 'baz']);
let set3 = new Set(function*() { yield* set1; yield* set2; }());
console.log(Array.from(set3)); // Result: [ 'foo', 'bar', 'baz' ]
Run Code Online (Sandbox Code Playgroud)
jfr*_*d00 33
由于我不明白的原因,您无法通过内置操作直接将一个Set的内容添加到另一个Set.
.forEach()检测到你正在传递另一个Set对象然后只是抓住该Set中的所有项目(这是我自己的Set对象 - 在有ES6 Set规范之前)的工作原理似乎是很自然的.但是,他们选择不以这种方式实施.
相反,您可以使用Map一行来完成:
var s = new Set([1,2,3]);
var t = new Set([4,5,6]);
t.forEach(s.add, s);
console.log(s); // 1,2,3,4,5,6
Run Code Online (Sandbox Code Playgroud)
并且,对于a Set,你可以这样做:
var s = new Map([["key1", 1], ["key2", 2]]);
var t = new Map([["key3", 3], ["key4", 4]]);
t.forEach(function(value, key) {
s.set(key, value);
});
Run Code Online (Sandbox Code Playgroud)
Asa*_*atz 16
编辑:
我将我的原始解决方案与其他解决方案建议进行基准测试,并发现它效率非常低.
基准测试本身非常有趣(链接)它比较了3种解决方案(越高越好):
- @ bfred.it的解决方案,逐个增加值(14,955 op/sec)
- @jameslk的解决方案,它使用自调用生成器(5,089 op/sec)
- 我自己的,使用减少和传播(3,434运算/秒)
如您所见,@ bfred.it的解决方案绝对是赢家.
表现+不变性
考虑到这一点,这里有一个稍微修改过的版本,它不会改变原始集合,并且可以将可变数量的iterables作为参数组合:
Run Code Online (Sandbox Code Playgroud)function union(...iterables) { const set = new Set(); for (let iterable of iterables) { for (let item of iterable) { set.add(item); } } return set; }用法:
Run Code Online (Sandbox Code Playgroud)const a = new Set([1, 2, 3]); const b = new Set([1, 3, 5]); const c = new Set([4, 5, 6]); union(a,b,c) // {1, 2, 3, 4, 5, 6}
我想建议另一种方法,使用reduce和spread运营商:
function union (sets) {
return sets.reduce((combined, list) => {
return new Set([...combined, ...list]);
}, new Set());
}
Run Code Online (Sandbox Code Playgroud)
用法:
const a = new Set([1, 2, 3]);
const b = new Set([1, 3, 5]);
const c = new Set([4, 5, 6]);
union([a, b, c]) // {1, 2, 3, 4, 5, 6}
Run Code Online (Sandbox Code Playgroud)
小费:
我们也可以利用rest运算符使界面更好一些:
function union (...sets) {
return sets.reduce((combined, list) => {
return new Set([...combined, ...list]);
}, new Set());
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以传递任意数量的集合参数,而不是传递一组数组:
union(a, b, c) // {1, 2, 3, 4, 5, 6}
Run Code Online (Sandbox Code Playgroud)
fre*_*nte 12
批准的答案很棒,但每次创建一个新的集合.
如果要改变现有对象,请使用辅助函数.
function concatSets(set, ...iterables) {
for (const iterable of iterables) {
for (const item of iterable) {
set.add(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
const setA = new Set([1, 2, 3]);
const setB = new Set([4, 5, 6]);
const setC = new Set([7, 8, 9]);
concatSets(setA, setB, setC);
// setA will have items 1, 2, 3, 4, 5, 6, 7, 8, 9
Run Code Online (Sandbox Code Playgroud)
function concatMaps(map, ...iterables) {
for (const iterable of iterables) {
for (const item of iterable) {
map.set(...item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
const mapA = new Map().set('S', 1).set('P', 2);
const mapB = new Map().set('Q', 3).set('R', 4);
concatMaps(mapA, mapB);
// mapA will have items ['S', 1], ['P', 2], ['Q', 3], ['R', 4]
Run Code Online (Sandbox Code Playgroud)
小智 5
要将集合合并到数组集合中,可以执行
var Sets = [set1, set2, set3];
var merged = new Set([].concat(...Sets.map(set => Array.from(set))));
Run Code Online (Sandbox Code Playgroud)
对于我来说有点神秘,为什么以下这些应该等效的至少在Babel中失败了:
var merged = new Set([].concat(...Sets.map(Array.from)));
Run Code Online (Sandbox Code Playgroud)