【发布时间】:2019-01-06 12:32:37
【问题描述】:
我想比较两个对象数组,如果它们的元素相同但顺序不同,则它们应该被视为相等。例如[{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]
}]
}]
数组也不能有唯一值(因为用户正在创建这个数组)。
正如@Koushik 和@tokland 所建议的那样,_.isEqualWith 可能会实现这一点。不幸的是,它可以从 lodashv4 获得,所以我不能使用它。
这个comment中也提到了类似的解决方案。
非常抱歉没有明确指定示例。小提琴有所有不同类型的案例。
【问题讨论】:
-
使用计数排序比较数组的内容。这将为您提供 O(n) 而不是您当前拥有的 O(n^2)。
-
@miradham,你能给我一个简单的例子或算法,说明如何用计数排序比较两个对象数组吗?我认为它只适用于数字数组。
-
通过计数排序,我的意思是,您可以散列值并检查其数量和存储值一次。但我说它可以提高性能是错误的。在您的示例对象中,具有相同键的对象可以有多个值,因此您必须检查每个值,这无论如何都会给您 O(n^2)。
标签: javascript lodash