web-dev-qa-db-ja.com

2つのオブジェクトのプロパティをJavascriptまたはlodashで浅く比較するにはどうすればよいですか?

下がらない浅い比較を行い、Javascriptまたはlodashのオブジェクト内のオブジェクトのコンテンツを比較する方法はありますか? lodashをチェックしましたが、不要な深い比較を実行しているようです。

var a = { x: 1, y: 2}
var b = { x: 1, y: 3}

たとえば、abを比較する方法はありますか?

18
_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;
}
_
20
Paul Draper

シンプルな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]
  );
34
dhilt

浅い場合と文字列と数値のみの場合があることに注意してください

function equals(obj1, obj2) {
  return Object.keys(obj1)
    .concat(Object.keys(obj2))
    .every(key => {
      return obj1[key] === obj2[key];
    });
}
5
Adara Hv

これは 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には、警告なしにライブラリ内のこのコードやその他のコードが削除または変更される可能性があることが明記されているため、使用する必要がある場合は、自分のプロジェクトにコピーすることをお勧めします。

4
mpen

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;
}
2
Ries Vriend

継承されたプロパティを無視し、NaNNaNに等しい「浅い」比較を行うには、次のようにします。各オブジェクトが同じ独自のプロパティを持ち、値が===または両方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関数を多少簡略化できます。

1
RobG
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;
}
0
mrmaclean89