假设我有以下对象数组
var firstDataSet = [
{'id': 123, 'name': 'ABC'},
{'id': 456, 'name': 'DEF'},
{'id': 789, 'name': 'GHI'},
{'id': 101, 'name': 'JKL'}
];
var secondDataSet = [
{'id': 123, 'name': 'ABC', 'xProp': '1q'},
{'id': 156, 'name': 'MNO', 'xProp': '2w'},
{'id': 789, 'name': 'GHI', 'xProp': '3e'},
{'id': 111, 'name': 'PQR', 'xProp': '4r'}
];
现在我想收集带有唯一对象的数组(匹配id
和name
),即
var firstDataSet = [
{'id': 123, 'name': 'ABC', 'xProp': '1q'},
{'id': 456, 'name': 'DEF'},
{'id': 789, 'name': 'GHI', 'xProp': '3e'},
{'id': 101, 'name': 'JKL'},
{'id': 156, 'name': 'MNO', 'xProp': '2w'},
{'id': 111, 'name': 'PQR', 'xProp': '4r'}
];
我可以用
收集ALLArray.prototype.unshift.apply(firstDataSet , secondDataSet );
但不确定如何过滤重复项。有什么建议吗?
编辑:我在两个不同阵列上的对象不相同。至少基于属性的数量。
答案 0 :(得分:3)
这是原始问题。
使用Set
:
Set对象允许您存储任何类型的唯一值,无论是原始值还是对象引用。
var list = ["{'id': 123, 'name': 'ABC'}", "{'id': 123, 'name': 'ABC'}"];
var unique_list = new Set(list); // returns Set {"{'id': 123, 'name': 'ABC'}"}
var list = Array.from(unique_list); // converts back to an array!
有关构建数组的更多方法,可以按照here的说明进行操作。 如果您无法使用ES6(定义{{1}}的内容),则可以使用旧版浏览器polyfill。
不幸的是,这些对象不再是严格重复的,并且不能使用Set
以友好的方式处理。
解决此类问题的最简单方法是迭代对象数组,识别具有重复属性值的对象,并使用Set
进行消除。
答案 1 :(得分:1)
我们将使用concat
合并两个数组,然后使用filter
过滤生成的数组。对于每个元素,我们将使用findIndex
找到具有相同id和名称的第一个元素的索引。如果该索引与当前索引相同,则意味着这是该id和名称的第一次出现,因此我们只是让它通过。否则,我们将在第一次出现时添加新字段,并将其过滤掉。
function combine(a1, a2) {
function match(e1, e2) { return e1.id === e2.id && e1.name === e2.name); }
return a1.concat(a2) . filter((e1, i, a) => {
let firstIndex = a.findIndex(e2 => match(e1, e2));
if (i === firstIndex) return true; // this is the first occurrence
a[firstIndex].xProp = e2.xProp; // copy over property
return false; // filter out
});
}
如果您想处理任意属性,而不仅仅是xProp
,请将相关行更改为
a[firstIndex] = Object.assign(e2, a[firstIndex]);
这将取代第一次出现,其结果是在当前事件的顶部复制其所有属性,包括它可能具有的任何其他属性。
强制免责声明:与往常一样,根据您的环境,您可能没有箭头功能,Array#findIndex
或Object.assign
。在这种情况下,必要时重写/填充/转换。
答案 2 :(得分:0)
这可能不是最有效的解决方案,但假设id始终是唯一的,它应该可以工作。
var firstDataSet = [
{'id': 123, 'name': 'ABC'},
{'id': 456, 'name': 'DEF'},
{'id': 789, 'name': 'GHI'},
{'id': 101, 'name': 'JKL'}
];
var secondDataSet = [
{'id': 123, 'name': 'ABC', 'xProp': '1q'},
{'id': 156, 'name': 'MNO', 'xProp': '2w'},
{'id': 789, 'name': 'GHI', 'xProp': '3e'},
{'id': 111, 'name': 'PQR', 'xProp': '4r'}
];
Array.prototype.unique = function() {
var o = {}, i, l = this.length, r = [];
for(i=0; i<l;i+=1) o[this[i]] = this[i];
for(i in o) r.push(o[i]);
return r;
};
function concatUnique(a, b, property) {
var arr = a.concat(b);
arr.sort(function(a,b) {
return Object.keys(b).length - Object.keys(a).length;
});
var ids = arr.map(function(obj){ return obj[property] }).unique();
return arr.filter(function(obj) {
if(ids.indexOf(obj[property]) > -1) {
ids.splice( ids.indexOf(obj[property]) , 1);
return true;
} else {
return false
}
});
}
var newArray = concatUnique(firstDataSet, secondDataSet, 'id');
答案 3 :(得分:0)
这可以通过扩展如下的Set
类来实现
var firstDataSet = [
{'id': 123, 'name': 'ABC'},
{'id': 456, 'name': 'DEF'},
{'id': 789, 'name': 'GHI'},
{'id': 101, 'name': 'JKL'}
];
var secondDataSet = [
{'id': 123, 'name': 'ABC', 'xProp': '1q'},
{'id': 156, 'name': 'MNO', 'xProp': '2w'},
{'id': 789, 'name': 'GHI', 'xProp': '3e'},
{'id': 111, 'name': 'PQR', 'xProp': '4r'}
];
Array.prototype.unshift.apply(firstDataSet , secondDataSet );
//console.log(firstDataSet)
class UniqueSet extends Set {
constructor(values) {
super(values);
const data = [];
for (let value of this) {
if (data.includes(JSON.parse(value.id))) {
this.delete(value);
} else {
data.push(value.id);
}
}
}
}
console.log(new UniqueSet(firstDataSet))
工作link