对象数组与lodash深度比较

问题描述 投票:0回答:6

我有 2 个对象数组,我将与它们进行深入比较

lodash

但是,我有一个问题:

> var x = [{a:1, b:2}, {c:3, d:4}];
> var y = [{b:2, a:1}, {d:4, c:3}];
> _.difference(x,y, _.isEqual);
[ { a: 1, b: 2 }, { c: 3, d: 4 } ]

我应该如何比较才能看到两者相等?

javascript arrays javascript-objects lodash
6个回答
62
投票

您可以将 differenceWith()isEqual() 比较器结合使用,并调用 isEmpty 来检查它们是否相等。

var isArrayEqual = function(x, y) {
  return _(x).differenceWith(y, _.isEqual).isEmpty();
};

var result1 = isArrayEqual(
  [{a:1, b:2}, {c:3, d:4}],
  [{b:2, a:1}, {d:4, c:3}]
);

var result2 = isArrayEqual(
  [{a:1, b:2, c: 1}, {c:3, d:4}],
  [{b:2, a:1}, {d:4, c:3}]
);

document.write([
  '<div><label>result1: ', result1, '</label></div>',
  '<div><label>result2: ', result2, '</label></div>',
].join(''));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.2/lodash.js"></script>

2018 年 6 月 22 日更新

此更新是为了回应以下评论:

@ryeballar 如果任何数组未定义,则返回 true。怎么会 你解决这个问题。先谢谢老哥了

differenceWith
文档中所述:

结果值的顺序和引用由第一个决定 数组。

这意味着只要第一个数组中的所有项目都与第二个数组中的其他所有项目匹配,那么

differenceWith
调用生成的数组将为空。

真正解决问题的另一种解决方案是使用

xorWith()
以及与上述解决方案相同的功能链。

var isArrayEqual = function(x, y) {
  return _(x).xorWith(y, _.isEqual).isEmpty();
};

var result1 = isArrayEqual(
  [{a:1, b:2}, {c:3, d:4}],
  [{b:2, a:1}, {d:4, c:3}]
);

var result2 = isArrayEqual(
  [{a:1, b:2, c: 1}, {c:3, d:4}],
  [{b:2, a:1}, {d:4, c:3}]
);

var result3 = isArrayEqual(
  [{a:1, b:2, c: 1}, {c:3, d:4}],
  [{b:2, a:1}, {d:4, c:3}, undefined]
);

console.log('result1:', result1);
console.log('result2:', result2);
console.log('result3:', result3);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>


32
投票

按照@ryeballar的回答,如果你只想导入特定的lodash方法,你可以使用这个符号:

import { isEmpty, isEqual, xorWith } from 'lodash';


export const isArrayEqual = (x, y) => isEmpty(xorWith(x, y, isEqual));


6
投票

仅当在第二个数组中找到当前项时,如果数组长度不同,则上面的

xorWith
differenceWith
的两个答案都不会计数。

var isArrayEqual = function(x, y) {
  return _(x).xorWith(y, _.isEqual).isEmpty();
};

var result = isArrayEqual(
  [{a:1, b:2}],
  [{a:1, b:2}, {a:1, b:2}]
);


console.log('result should be false:', result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

在这种特殊情况下,我们还必须比较两个数组的长度。

const isArrayEqual = function(x, y) {
  const isSameSize = _.size(x) === _.size(y);
  return isSameSize && _(x).xorWith(y, _.isEqual).isEmpty();
};

const result = isArrayEqual(
  [{a:1, b:2}],
  [{a:1, b:2}, {a:1, b:2}]
);


console.log('result should be false:', result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>


2
投票

我更喜欢纯JS,因为我没有耐心学习下划线或lodash。所以我发明了我一直梦想的东西。

Object.prototype.compare()
。 v0.0.2 虽然只进行了浅层比较,但足以解决这个问题。

Object.prototype.compare = function(o){
  var ok = Object.keys(this);
  return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
var obj1 = {a:1,b:2,c:3},
    obj2 = {c:3,a:1,b:2},
    obj3 = {b:2,c:3,a:7};

document.write ("<pre>" + obj1.compare(obj2) + "</pre>\n");
document.write ("<pre>" + obj2.compare(obj3) + "</pre>\n");
document.write ("<pre>" + new Object({a:1, b:2, c:3}).compare({c:3,b:2,a:1,d:0}) + "</pre>\n");

酷...那么让我们继续这个问题...我想...既然我们已经有了一个

Object.prototype.compare()
,那么发明
Array.prototype.compare()
应该绝对没有坏处。这次让我们做得更聪明一些。它将区分原语和对象。另一件事是,数组是有序的;所以在我的书中,
[1,2]
不等于
[2,1]
。这也使工作变得更简单。

Object.prototype.compare = function(o){
  var ok = Object.keys(this);
  return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
Array.prototype.compare = function(a){
  return this.every((e,i) => typeof a[i] === "object" ? a[i].compare(e) : a[i] === e);
}
var x = [{a:1, b:2}, {c:3, d:4}],
    y = [{b:2, a:1}, {d:4, c:3}],
    a = [1,2,3,4,5],
    b = [1,2,3,4,5],
    p = "fourtytwo",
    r = "thirtyseven",
    n = 42,
    m = 37;
document.writeln(x.compare(y)); // the question is answered here
document.writeln(a.compare(b));
document.writeln(p.compare(r)); // these primitives end up at Object prototype
document.writeln(n.compare(m)); // so modify Object.prototype.compare () accordingly


0
投票

结合解决方案 1解决方案 2 的答案并举例。

const isArrayEqual = (x, y) => (
_.size(x) === _.size(y) && _.isEmpty(_.xorWith(x, y, _.isEqual))
);

const result1 = isArrayEqual(
  [{a:1, b:2}],
  [{a:1, b:2}, {a:1, b:2}]
);

const result2 = isArrayEqual(
  [{a:1, b:2},{a:2, b:2}],
  [{a:1, b:2}, {a:1, b:2}]
);

const result3 = isArrayEqual(
  [{a:1, b:2},{a:1, b:2}],
  [{a:1, b:2}, {a:1, b:2}]
);

// if order is changed
const result4 = isArrayEqual(
  [{a:2, b:2},{a:1, b:2}],
  [{a:1, b:2}, {a:2, b:2}]
);

console.log('result1 should be false:', result1);
console.log('result2 should be false:', result2);
console.log('result3 should be true:', result3);
console.log('result4 should be true:', result4);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

在Js解决方案中,一行代码:

import { size, isEmpty, isEqual, xorWith } from "lodash";    
export const isArrayOfObjectsEqual = (x, y) => size(x) === size(y) && isEmpty(xorWith(x, y, isEqual));

0
投票

_.isEqual
(lodash)可以比较对象数组。

//true
var result1 = _.isEqual(
  [{a:1, b:2}],
  [{a:1, b:2}]
);

//false
var result2 = _.isEqual(
  [{a:1, b:2}],
  [{a:1}]
);

//false
var result3 = _.isEqual(
  [{a:1, b:2}],
  []
);

document.write([
  '<div><label>result1: ', result1, '</label></div>',
  '<div><label>result2: ', result2, '</label></div>',
  '<div><label>result2: ', result3, '</label></div>',
].join(''));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js"></script>

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.