web-dev-qa-db-ja.com

lodashとのオブジェクトの深い比較の配列

lodashと深く比較するオブジェクトの配列が2つあります

しかし、私はそれに問題があります:

> 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 } ]

両方が等しいことを確認するにはどうすればいいですか?

13
Archer

isEqual() コンパレータで differenceWith() を使用し、 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ドキュメントに記載されているとおり:

結果値の順序と参照は、最初の配列によって決定されます。

これは、最初の配列のすべての項目が2番目の配列の他のすべてと一致する限り、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>_
30
ryeballar

私はアンダースコアやロダッシュを学ぶ忍耐を持っていないので、純粋なJSが好きです。だから私は長い間夢見てきたものを発明します。 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つは、配列が順序付けられていることです。だから私の本では[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
3
Redu

@ryeballarの回答に続いて、特定のlodashメソッドのみをインポートする場合は、この表記を使用できます。

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


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

2
Anita