有没有一个简单的方法来合并ES6映射在一起(像Object.assign)?说到这里,ES6集合(比如Array.concat)呢?
当前回答
你可以使用spread语法将它们合并在一起:
const map1 = {a: 1, b: 2}
const map2 = {b: 1, c: 2, a: 5}
const mergedMap = {...a, ...b}
=> {a: 5, b: 1, c: 2}
其他回答
不,它们没有内置操作,但你可以很容易地创建自己的操作:
Map.prototype.assign = function(...maps) {
for (const m of maps)
for (const kv of m)
this.add(...kv);
return this;
};
Set.prototype.concat = function(...sets) {
const c = this.constructor;
let res = new (c[Symbol.species] || c)();
for (const set of [this, ...sets])
for (const v of set)
res.add(v);
return res;
};
被认可的答案很好,但每次都会创建一个新的集合。
如果要更改现有对象,请使用helper函数
在不久的将来,你可以只使用setA.union(setB)
Set
function concatSets(set, ...iterables) {
for (const iterable of iterables) {
for (const item of iterable) {
set.add(item);
}
}
}
用法:
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
Map
function concatMaps(map, ...iterables) {
for (const iterable of iterables) {
for (const item of iterable) {
map.set(...item);
}
}
}
用法:
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]
以下是我使用生成器的解决方案:
地图:
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' ] ]
集:
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' ]
编辑:
I benchmarked my original solution against other solutions suggests here and found that it is very inefficient. The benchmark itself is very interesting (link) It compares 3 solutions (higher is better): @fregante (formerly called @bfred.it) solution, which adds values one by one (14,955 op/sec) @jameslk's solution, which uses a self invoking generator (5,089 op/sec) my own, which uses reduce & spread (3,434 op/sec) As you can see, @fregante's solution is definitely the winner. Performance + Immutability With that in mind, here's a slightly modified version which doesn't mutates the original set and excepts a variable number of iterables to combine as arguments: function union(...iterables) { const set = new Set(); for (const iterable of iterables) { for (const item of iterable) { set.add(item); } } return set; } Usage: 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());
}
用法:
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}
Tip:
我们还可以使用rest操作符来使界面更好:
function union (...sets) {
return sets.reduce((combined, list) => {
return new Set([...combined, ...list]);
}, new Set());
}
现在,我们不再传递一个集合数组,而是可以传递任意数量的集合参数:
union(a, b, c) // {1, 2, 3, 4, 5, 6}
将集合转换为数组,将它们平直,最后构造函数将惟一化。
const union = (...sets) => new Set(sets.map(s => [...s]).flat());