有没有一个简单的方法来合并ES6映射在一起(像Object.assign)?说到这里,ES6集合(比如Array.concat)呢?
当前回答
一个很好的解决方案,无论你是否有两个或更多的映射合并是将它们作为一个数组,并使用以下:
Array.prototype.merge = function () {
return this.reduce((p, c) => Object.assign(c, p), {});
};
其他回答
你可以使用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}
要合并数组集合中的集合,您可以执行
var Sets = [set1, set2, set3];
var merged = new Set([].concat(...Sets.map(set => Array.from(set))));
对我来说有点神秘的是,为什么下面这些应该是等价的,但至少在巴别塔失败了:
var merged = new Set([].concat(...Sets.map(Array.from)));
不,它们没有内置操作,但你可以很容易地创建自己的操作:
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;
};
一个很好的解决方案,无论你是否有两个或更多的映射合并是将它们作为一个数组,并使用以下:
Array.prototype.merge = function () {
return this.reduce((p, c) => Object.assign(c, p), {});
};
出于我不理解的原因,您不能直接使用内置方法将一个Set的内容添加到另一个Set。像联合、交叉、合并等操作…是非常基本的集合操作,但不是内置的。幸运的是,您可以相当容易地自己构建这些。
[2021年新增]-现在有一个提议为这些类型的操作添加新的Set/Map方法,但实施的时间还不清楚。他们似乎处于规范过程的第二阶段。
要实现合并操作(将一个Set的内容合并到另一个Set中,或将一个Map的内容合并到另一个Map中),你可以使用单个.forEach()行来完成:
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
对于Map,你可以这样做:
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);
});
或者,在ES6语法中:
t.forEach((value, key) => s.set(key, value));
[2021年新增]
由于现在有一个新的Set方法的官方提议,你可以使用这个polyfill提议的.union()方法,它将在ES6+版本的ECMAScript中工作。注意,根据规范,这将返回一个新Set,它是另外两个Set的并集。它不会将一个集合的内容合并到另一个集合中,这实现了建议中指定的类型检查。
if (!Set.prototype.union) {
Set.prototype.union = function(iterable) {
if (typeof this !== "object") {
throw new TypeError("Must be of object type");
}
const Species = this.constructor[Symbol.species];
const newSet = new Species(this);
if (typeof newSet.add !== "function") {
throw new TypeError("add method on new set species is not callable");
}
for (item of iterable) {
newSet.add(item);
}
return newSet;
}
}
或者,这里有一个更完整的版本,它对ECMAScript过程进行了建模,以更完整地获得物种构造函数,并且已经适应于在甚至可能没有Symbol或有Symbol的旧版本Javascript上运行。种类:
if (!Set.prototype.union) {
Set.prototype.union = function(iterable) {
if (typeof this !== "object") {
throw new TypeError("Must be of object type");
}
const Species = getSpeciesConstructor(this, Set);
const newSet = new Species(this);
if (typeof newSet.add !== "function") {
throw new TypeError("add method on new set species is not callable");
}
for (item of iterable) {
newSet.add(item);
}
return newSet;
}
}
function isConstructor(C) {
return typeof C === "function" && typeof C.prototype === "object";
}
function getSpeciesConstructor(obj, defaultConstructor) {
const C = obj.constructor;
if (!C) return defaultConstructor;
if (typeof C !== "function") {
throw new TypeError("constructor is not a function");
}
// use try/catch here to handle backward compatibility when Symbol does not exist
let S;
try {
S = C[Symbol.species];
if (!S) {
// no S, so use C
S = C;
}
} catch (e) {
// No Symbol so use C
S = C;
}
if (!isConstructor(S)) {
throw new TypeError("constructor function is not a constructor");
}
return S;
}
供参考,如果你想要一个内置Set对象的简单子类,它包含一个.merge()方法,你可以使用这个:
// subclass of Set that adds new methods
// Except where otherwise noted, arguments to methods
// can be a Set, anything derived from it or an Array
// Any method that returns a new Set returns whatever class the this object is
// allowing SetEx to be subclassed and these methods will return that subclass
// For this to work properly, subclasses must not change behavior of SetEx methods
//
// Note that if the contructor for SetEx is passed one or more iterables,
// it will iterate them and add the individual elements of those iterables to the Set
// If you want a Set itself added to the Set, then use the .add() method
// which remains unchanged from the original Set object. This way you have
// a choice about how you want to add things and can do it either way.
class SetEx extends Set {
// create a new SetEx populated with the contents of one or more iterables
constructor(...iterables) {
super();
this.merge(...iterables);
}
// merge the items from one or more iterables into this set
merge(...iterables) {
for (let iterable of iterables) {
for (let item of iterable) {
this.add(item);
}
}
return this;
}
// return new SetEx object that is union of all sets passed in with the current set
union(...sets) {
let newSet = new this.constructor(...sets);
newSet.merge(this);
return newSet;
}
// return a new SetEx that contains the items that are in both sets
intersect(target) {
let newSet = new this.constructor();
for (let item of this) {
if (target.has(item)) {
newSet.add(item);
}
}
return newSet;
}
// return a new SetEx that contains the items that are in this set, but not in target
// target must be a Set (or something that supports .has(item) such as a Map)
diff(target) {
let newSet = new this.constructor();
for (let item of this) {
if (!target.has(item)) {
newSet.add(item);
}
}
return newSet;
}
// target can be either a Set or an Array
// return boolean which indicates if target set contains exactly same elements as this
// target elements are iterated and checked for this.has(item)
sameItems(target) {
let tsize;
if ("size" in target) {
tsize = target.size;
} else if ("length" in target) {
tsize = target.length;
} else {
throw new TypeError("target must be an iterable like a Set with .size or .length");
}
if (tsize !== this.size) {
return false;
}
for (let item of target) {
if (!this.has(item)) {
return false;
}
}
return true;
}
}
module.exports = SetEx;
这意味着在它自己的文件setex.js中,然后你可以在node.js中使用require()并取代内置的Set。
推荐文章
- 在setInterval中使用React状态钩子时状态不更新
- 使用JavaScript显示/隐藏'div'
- 使用JavaScript获取所选的选项文本
- AngularJS模板中的三元运算符
- 让d3.js可视化布局反应灵敏的最好方法是什么?
- 原型的目的是什么?
- 检查jquery是否使用Javascript加载
- 将camelCaseText转换为标题大小写文本
- 如何在JavaScript客户端截屏网站/谷歌怎么做的?(无需存取硬盘)
- 如何在JavaScript中遍历表行和单元格?
- jQuery map vs. each
- 自定义异常类型
- 窗口。Onload vs <body Onload =""/>
- 不能与文件列表一起使用forEach
- Angular 2 Hover事件