我想比较两个对象数组,如果它们的元素相同但顺序不同,则应将它们视为相等。例如[{a:1}, {b:2}] and [{b:2}, {a:1}]
我正在使用lodash-v3的isEqual
,它可以比较两个值,但是只有在数组中的顺序相同时它才为true,因此我实现了一个函数,该函数以递归方式比较元素。
function deepEqual(data1, data2) {
data1 = _.cloneDeep(data1);
data2 = _.cloneDeep(data2);
function isDeepEqual(val1, val2) {
if (_.isArray(val1) && _.isArray(val2)) {
if (val1.length === val2.length) {
for (let id1 in val1) {
let hasMatch = false;
let matchOnIndex = -1;
for (let id2 in val2) {
if (isDeepEqual(val1[id1], val2[id2])) {
hasMatch = true;
matchOnIndex = id2;
break;
}
}
if (hasMatch) {
val2.splice(matchOnIndex, 1);
} else {
return false;
}
}
return true;
} else {
return false;
}
}
if (_.isPlainObject(val1) && _.isPlainObject(val2)) {
if (Object.keys(val1).length === Object.keys(val2).length) {
for (let temp1 in val1) {
if (!isDeepEqual(val1[temp1], val2[temp1])) {
return false;
}
}
return true;
} else {
return false;
}
}
return _.isEqual(val1, val2);
}
return isDeepEqual(data1, data2);
}
以上功能有效,但是如何明智地提高其性能? 如果有lodash3的任何简单实现对我也适用。
链接到上述函数的fiddle。
编辑:
两个对象数组可以嵌套, 例如
[{
a:1,
b:[{
c: [1, 2]
},
{
d: [3, 4]
}]
},{
e:1,
f:[{
g: [5, 6]
},
{
h: [7, 8]
}]
}]
和
[{
e:1,
f:[{
h: [8, 7]
},{
g: [6, 5]
}]
},{
a:1,
b:[{
d: [4, 3]
},{
c: [2, 1]
}]
}]
数组也不能具有唯一值(因为用户正在创建此数组)。
可以使用_.isEqualWith
来实现,如@Koushik和@tokland建议的那样。不幸的是,可以从lodashv4获得它,所以我不能使用它。
comment中也提到了类似的解决方案。
非常抱歉,没有明确说明示例。小提琴有所有不同类型的案例。
答案 0 :(得分:0)
我认为这就是您想要的
var first = [{ a: 1 }, { b: 2 }];
var second = [{ b: 2 }, { a: 1 }];
function comparer(otherArray){
return function(current){
return otherArray.filter(function(other){
return other.a == current.a && other.b == current.b
}).length == 0;
}
}
var onlyInA = first.filter(comparer(second));
var onlyInB = second.filter(comparer(first));
result = (onlyInA.concat(onlyInB)).length===0;
console.log(result);
答案 1 :(得分:0)
函数_.isEqualWith应该是起点。现在,有很多方法可以实现它。您可以通过为数组中的项目定义顺序来使其非常有效。使用id
作为键的示例:
function isEqualConsideringArraysAsSets(obj1, obj2, key) {
const customizer = (objValue, othValue) => {
if (_(objValue).isArray() && _(othValue).isArray()) {
return _.size(objValue) === _.size(othValue) &&
_.zip(_.sortBy(objValue, key), _.sortBy(othValue, key))
.every(([val1, val2]) => isEqualConsideringArraysAsSets(val1, val2));
}
};
return _.isEqualWith(obj1, obj2, customizer);
}
console.log(isEqualConsideringArraysAsSets([{id: 1}, {id: 2}], [{id: 2}, {id: 1}], "id"))
答案 2 :(得分:0)
简单检查一个Object
中每个array
出现在另一个array
中并具有相同的length
(两个数组)怎么样?
let isEqualArray = (arr1, arr2) => (
arr1 === arr2 ||
arr1.length === arr2.length &&
!arr1.some(a=> !arr2.find(b=>_.isEqual(a,b)))
)
let a1 = [{a:1}, {b:2}],
a2 = [{b:2}, {a:1}];
let isEqualArray = (arr1, arr2) => (
arr1 === arr2 ||
arr1.length === arr2.length &&
!arr1.some(a=> !arr2.find(b=>_.isEqual(a,b)))
)
console.log(isEqualArray(a1,a2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
_.isEqual
或_.isEqualWith
与定制器的结合使用,具体取决于您要如何比较两个对象!
注意:当阵列中有重复项时,这将不会100%起作用,但是它将至少确认一个阵列中的所有项都存在于另一阵列中。您可以进行反向检查,也可以应用唯一方法对重复的数组执行此比较。