下がらない浅い比較を行い、Javascriptまたはlodashのオブジェクト内のオブジェクトのコンテンツを比較する方法はありますか? lodashをチェックしましたが、不要な深い比較を実行しているようです。
var a = { x: 1, y: 2}
var b = { x: 1, y: 3}
たとえば、a
とb
を比較する方法はありますか?
_function areEqualShallow(a, b) {
for(var key in a) {
if(!(key in b) || a[key] !== b[key]) {
return false;
}
}
for(var key in b) {
if(!(key in a) || a[key] !== b[key]) {
return false;
}
}
return true;
}
_
ノート:
これは浅いため、areEqualShallow({a:{}}, {a:{}})
はfalseです。
areEqualShallow({a:undefined}, {})
はfalseです。
これには、プロトタイプのプロパティが含まれます。
これは_===
_比較を使用します。私はそれがあなたが望むものだと思います。 _NaN === NaN
_は、予期しない結果をもたらす可能性がある1つのケースです。 _===
_が必要なものでない場合は、必要な比較に置き換えます。
編集:同じキーが各オブジェクトにある場合、
_function areEqualShallow(a, b) {
for(var key in a) {
if(a[key] !== b[key]) {
return false;
}
}
return true;
}
_
シンプルなES6アプローチ:
const shallowCompare = (obj1, obj2) =>
Object.keys(obj1).length === Object.keys(obj2).length &&
Object.keys(obj1).every(key => obj1[key] === obj2[key]);
ここで、次の比較が失敗するはずのオブジェクトキーの量の等価性チェックを追加しました(通常は考慮されない重要なケース)。
shallowCompare({ x: 1, y: 3}, { x: 1, y: 3, a: 1}); // false
2019アップデート。 Andrew Rasmussenのコメントに従って、undefined
のケースも考慮する必要があります。以前のアプローチの問題は、次の比較がtrue
を返すことです。
({ foo: undefined })['foo'] === ({ bar: undefined })['foo'] // true
そのため、明示的なキーの存在チェックが必要です。そして、それはhasOwnProperty
で行うことができます:
const shallowCompare = (obj1, obj2) =>
Object.keys(obj1).length === Object.keys(obj2).length &&
Object.keys(obj1).every(key =>
obj2.hasOwnProperty(key) && obj1[key] === obj2[key]
);
浅い場合と文字列と数値のみの場合があることに注意してください
function equals(obj1, obj2) {
return Object.keys(obj1)
.concat(Object.keys(obj2))
.every(key => {
return obj1[key] === obj2[key];
});
}
これは fbjs から解除されます:
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*
*/
/*eslint-disable no-self-compare */
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is(x, y) {
// SameValue algorithm
if (x === y) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
}
/**
* Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments.
* Returns true when the values of all keys are strictly equal.
*/
function shallowEqual(objA, objB) {
if (is(objA, objB)) {
return true;
}
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
return false;
}
var keysA = Object.keys(objA);
var keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
for (var i = 0; i < keysA.length; i++) {
if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
return false;
}
}
return true;
}
module.exports = shallowEqual;
READMEには、警告なしにライブラリ内のこのコードやその他のコードが削除または変更される可能性があることが明記されているため、使用する必要がある場合は、自分のプロジェクトにコピーすることをお勧めします。
Paul Draperのソリューションは、2番目のパスで比較を削除することで最適化できます。
function areEqualShallow(a, b) {
for (let key in a) {
if (!(key in b) || a[key] !== b[key]) {
return false;
}
}
for (let key in b) {
if (!(key in a)) {
return false;
}
}
return true;
}
継承されたプロパティを無視し、NaN
をNaN
に等しい「浅い」比較を行うには、次のようにします。各オブジェクトが同じ独自のプロパティを持ち、値が===
または両方NaN
:
function checkProperties(a, b) {
var equal = true;
// For each property of a
for (var p in a) {
// Check that it's an own property
if (a.hasOwnProperty(p)) {
// Check that b has a same named own property and that the values
// are === or both are NaN
if (!b.hasOwnProperty(p) ||
(b[p] !== a[p] && !(typeof b[p] == 'number' && typeof a[p] == 'number' && isNaN(b[p] && isNaN(a[p]))))) {
// If not, set equal to false
equal = false;
}
}
// If equal is false, stop processing properties
if (!equal) break;
}
return equal;
}
Object.keysのような最近の機能を使用して独自のプロパティを取得し、
function checkProperties(a, b) {
return Object.keys(a).every(function(p) {
return b.hasOwnProperty(p) &&
(b[p] == a[p] || (typeof a[p] == 'number' && typeof b[p] == 'number' && isNaN(b[p]) && isNaN(a[p])));
});
}
// Compare a to b and b to a
function areEqualShallow(a, b) {
return checkProperties(a, b) && checkProperties(b, a);
}
// Minimal testing
var a = {foo:'a', bar:2};
var b = {foo:'a', bar:2};
var c = {foo:'c', bar:2};
var d = {foo:'a', bar:2, fum:0};
console.log('a equal to b? ' + areEqualShallow(a,b)); // true
console.log('a equal to c? ' + areEqualShallow(a,c)); // false
console.log('a equal to d? ' + areEqualShallow(a,d)); // false
新しい機能を使用すると、checkProperties関数を多少簡略化できます。
var a = { x: 1, y: 2}
var b = { x: 1, y: 3}
function shalComp (obj1, obj2) {
var verdict = true;
for (var key in obj1) {
if (obj2[key] != obj1[key]) {
verdict = false;
}
}
return verdict;
}