दो जावास्क्रिप्ट वस्तुओं के लिए समानता कैसे निर्धारित करें?


669

एक सख्त समानता ऑपरेटर आपको बताएगा कि क्या दो ऑब्जेक्ट प्रकार समान हैं। हालांकि, यह बताने का एक तरीका है कि क्या दो ऑब्जेक्ट समान हैं, बहुत कुछ जावा में हैश कोड मान की तरह है ?

स्टैक ओवरफ्लो प्रश्न क्या जावास्क्रिप्ट में किसी प्रकार का हैशकोड फ़ंक्शन है? इस प्रश्न के समान है, लेकिन इसके लिए अधिक अकादमिक उत्तर की आवश्यकता है। ऊपर का परिदृश्य दर्शाता है कि एक होना क्यों आवश्यक होगा, और यदि कोई समतुल्य समाधान है तो मैं सोच रहा हूँ ।


3
इस प्रश्न पर भी नजर डालें। stackoverflow.com/q/1068834/1671639
प्रवीण

37
ध्यान दें, जावा में भी, a.hashCode() == b.hashCode()इसका मतलब यह नहीं है कि aइसके बराबर है b। यह एक आवश्यक शर्त है, पर्याप्त नहीं है।
हेनजी

Pls इस
क्यू

2
यदि आपको अपने कोड में वस्तुओं की तुलना करने की जरूरत है, तो आप शायद अपने कोड को गलत लिख रहे हैं। बेहतर सवाल यह हो सकता है: "मैं इस कोड को कैसे लिख सकता हूं ताकि मुझे वस्तुओं की तुलना न करनी पड़े?"
th317erd

3
@ th317erd क्या आप खुद को समझा सकते हैं? ...
एल मैक

जवाबों:


175

संक्षिप्त उत्तर

सरल उत्तर है: नहीं, यह निर्धारित करने के लिए कोई सामान्य साधन नहीं है कि कोई वस्तु आपके अर्थ में किसी अन्य के बराबर है। अपवाद तब होता है जब आप सख्ती से किसी वस्तु के बारे में सोच रहे होते हैं।

लंबा जवाब

अवधारणा एक समान पद्धति की है जो किसी वस्तु के दो अलग-अलग उदाहरणों की तुलना करके यह इंगित करती है कि वे मूल्य स्तर पर समान हैं या नहीं। हालांकि, यह विशिष्ट प्रकार पर निर्भर करता है कि कैसे एक Equalsविधि को लागू किया जाना चाहिए। आदिम मूल्यों वाले गुणों की एक पुनरावृत्ति तुलना पर्याप्त नहीं हो सकती है, अच्छी तरह से ऐसी विशेषताएँ हो सकती हैं जिन्हें ऑब्जेक्ट मान का हिस्सा नहीं माना जाता है। उदाहरण के लिए,

 function MyClass(a, b)
 {
     var c;
     this.getCLazy = function() {
         if (c === undefined) c = a * b // imagine * is really expensive
         return c;
     }
  }

इस उपरोक्त मामले में, cयह निर्धारित करना वास्तव में महत्वपूर्ण नहीं है कि क्या MyClass के दो उदाहरण समान हैं, केवल aऔर bमहत्वपूर्ण हैं। कुछ मामलों में cउदाहरणों के बीच अंतर हो सकता है और फिर भी तुलना के दौरान महत्वपूर्ण नहीं हो सकता है।

ध्यान दें कि यह मुद्दा तब लागू होता है जब सदस्य स्वयं भी एक प्रकार के उदाहरण हो सकते हैं और इन सभी को समानता का निर्धारण करने के लिए साधन की आवश्यकता होगी।

आगे की जटिल बातें यह है कि जावास्क्रिप्ट में डेटा और विधि के बीच का अंतर धुंधला है।

एक वस्तु एक विधि का संदर्भ दे सकती है जिसे एक इवेंट हैंडलर के रूप में कहा जाना है, और यह संभवतः इसके 'मूल्य राज्य' का हिस्सा नहीं माना जाएगा। जबकि एक अन्य वस्तु को अच्छी तरह से एक फ़ंक्शन सौंपा जा सकता है जो एक महत्वपूर्ण गणना करता है और इस तरह इस उदाहरण को दूसरों से अलग बनाता है क्योंकि यह एक अलग फ़ंक्शन का संदर्भ देता है।

एक ऐसी वस्तु के बारे में जो किसी अन्य फ़ंक्शन द्वारा अपने मौजूदा प्रोटोटाइप विधियों में से एक से अधिक है? क्या इसे अभी भी दूसरे उदाहरण के बराबर माना जा सकता है कि यह अन्यथा समान है? यह प्रश्न केवल प्रत्येक प्रकार के लिए प्रत्येक विशिष्ट मामले में उत्तर दिया जा सकता है।

जैसा कि पहले कहा गया था, अपवाद एक कड़ाई से टाइप की गई वस्तु होगी। जिस मामले में एकमात्र समझदार विकल्प प्रत्येक सदस्य की पुनरावृत्ति और पुनरावर्ती तुलना है। फिर भी किसी से पूछना होगा कि किसी फ़ंक्शन का 'मान' क्या है?


175
यदि आप अंडरस्कोर का उपयोग कर रहे हैं, तो आप बस कर सकते हैं_.isEqual(obj1, obj2);
chovy

12
@ हर्ष, जवाब देने में विफल रहा क्योंकि कोई भी समाधान नहीं है। जावा में भी, समानता की तुलना करने के लिए कोई चांदी की गोली नहीं है और सही तरीके से लागू करने के लिए .equalsविधि तुच्छ नहीं है, यही कारण है कि इस तरह के एक विषय प्रभावी जावा में समर्पित है ।
lcn

3
@ कुमार हर्ष, क्या दो वस्तुओं को समान बनाता है, बहुत ही विशिष्ट अनुप्रयोग है; किसी वस्तु की प्रत्येक संपत्ति को आवश्यक रूप से ध्यान में नहीं रखा जाना चाहिए, इसलिए किसी वस्तु की प्रत्येक संपत्ति को भंग करना एक ठोस समाधान नहीं है।
सेथरो १ro

googled javascript equality object, मिला tl; dr रिप्लाई, one-liner से @chovy कमेंट लिया। धन्यवाद
एंड्रिया

यदि कोणीय का उपयोग कर रहे हैं, तो आपके पासangular.equals
नाविक

506

पहिया को क्यों मजबूत करें? दे दो Lodash एक कोशिश। इसमें कई तरह के कार्य होते हैं जैसे कि इस्कल ()

_.isEqual(object, other);

यह बल को प्रत्येक कुंजी मान की जांच करेगा - इस पृष्ठ पर अन्य उदाहरणों की तरह - यदि वे ब्राउज़र में उपलब्ध हैं तो ECMAScript 5 और देशी अनुकूलन का उपयोग कर सकते हैं।

नोट: पहले इस जवाब में अंडरस्कोर.ज की सिफारिश की गई थी , लेकिन लॉश ने बग्स को ठीक करने और स्थिरता के साथ मुद्दों को संबोधित करने का एक बेहतर काम किया है।


27
अंडरस्कोर का आईक्वल फ़ंक्शन बहुत अच्छा है (लेकिन आपको इसका उपयोग करने के लिए उनकी लाइब्रेरी में खींचना होगा - लगभग 3K काटा हुआ)।
mckoss

29
यदि आप यह देखते हैं कि अंडरस्कोर आपको क्या देता है, तो आप इसे खींचने में पछतावा नहीं करेंगे
पांडा

6
यहां तक ​​कि अगर आप एक निर्भरता के रूप में अंडरस्कोर नहीं कर सकते हैं, तो आइक्वल फ़ंक्शन को बाहर निकालें, लाइसेंस आवश्यकताओं को पूरा करें और आगे बढ़ें। यह स्टैकओवरफ्लो पर उल्लिखित सबसे व्यापक समानता परीक्षण है।
डेल एंडरसन

7
अंडरडकोर का एक कांटा है जिसे LoDash कहा जाता है और यह लेखक इस तरह की निरंतरता के मुद्दों से बहुत चिंतित है। LoDash के साथ परीक्षण करें और देखें कि आपको क्या मिलता है।
CoolAJ86

6
यदि आप पूरी लाइब्रेरी npmjs.com/package/lodash.isequal
Rob Fox

161

जब वे स्मृति में एक ही स्थान को संदर्भित करते हैं, तो ऑब्जेक्ट के लिए जावास्क्रिप्ट में डिफ़ॉल्ट समानता ऑपरेटर सही पैदावार देता है।

var x = {};
var y = {};
var z = x;

x === y; // => false
x === z; // => true

यदि आपको एक अलग समानता ऑपरेटर की आवश्यकता होती है, तो आपको एक equals(other)विधि जोड़ने की आवश्यकता होगी , या ऐसा कुछ अपनी कक्षाओं में और आपके समस्या डोमेन की बारीकियों से पता चलेगा कि वास्तव में इसका क्या मतलब है।

यहाँ एक खेल कार्ड उदाहरण है:

function Card(rank, suit) {
  this.rank = rank;
  this.suit = suit;
  this.equals = function(other) {
     return other.rank == this.rank && other.suit == this.suit;
  };
}

var queenOfClubs = new Card(12, "C");
var kingOfSpades = new Card(13, "S");

queenOfClubs.equals(kingOfSpades); // => false
kingOfSpades.equals(new Card(13, "S")); // => true

यदि ऑब्जेक्ट को JSON स्ट्रिंग में परिवर्तित किया जा सकता है, तो यह एक समान () फ़ंक्शन को सरल बनाता है।
scotts

3
@scotts हमेशा नहीं। वस्तुओं को JSON में बदलना और तारों की तुलना करना तंग छोरों में जटिल वस्तुओं के लिए कम्प्यूटेशनल रूप से गहन हो सकता है। साधारण वस्तुओं के लिए यह शायद ज्यादा मायने नहीं रखता है, लेकिन वास्तव में यह वास्तव में आपकी विशिष्ट स्थिति पर निर्भर करता है। एक सही समाधान ऑब्जेक्ट आईडी की तुलना या प्रत्येक संपत्ति की जांच के रूप में सरल हो सकता है, लेकिन इसकी शुद्धता पूरी तरह से समस्या डोमेन द्वारा निर्धारित की जाती है।
डेनियल एक्स मूर

क्या हमें डेटा प्रकार की तुलना नहीं करनी चाहिए? अन्य को वापस करें। क्रैंक === यह। क्रैंक && अन्य। केस === यह। केस;
देवसंतीश

1
@ देवाशीष शायद नहीं। जावास्क्रिप्ट में प्रकार बहुत तेज और ढीले होते हैं, लेकिन यदि आपके डोमेन प्रकार महत्वपूर्ण हैं तो आप प्रकारों को भी जांचना चाह सकते हैं।
डैनियल एक्स मूर

7
@scot JSON को परिवर्तित करने के साथ अन्य समस्या यह है कि स्ट्रिंग में गुणों का क्रम महत्वपूर्ण हो जाता है। {x:1, y:2}! =={y:2, x:1}
स्टिज डे विट

81

यदि आप AngularJS में काम कर रहे हैं , तो angular.equalsफ़ंक्शन यह निर्धारित करेगा कि क्या दो ऑब्जेक्ट समान हैं। में Ember.js उपयोग isEqual

  • angular.equals- इस विधि पर अधिक के लिए डॉक्स या स्रोत देखें । यह सरणियों पर भी गहरी तुलना करता है।
  • Ember.js isEqual- इस विधि पर अधिक के लिए डॉक्स या स्रोत देखें । यह सरणियों पर एक गहरी तुलना नहीं करता है।

var purple = [{"purple": "drank"}];
var drank = [{"purple": "drank"}];

if(angular.equals(purple, drank)) {
    document.write('got dat');
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>


66

यह मेरा संस्करण है। यह नई Object.keys सुविधा का उपयोग कर रहा है जिसे ES5 में पेश किया गया है और + , + और + से विचार / परीक्षण किए गए हैं :

function objectEquals(x, y) {
    'use strict';

    if (x === null || x === undefined || y === null || y === undefined) { return x === y; }
    // after this just checking type of one would be enough
    if (x.constructor !== y.constructor) { return false; }
    // if they are functions, they should exactly refer to same one (because of closures)
    if (x instanceof Function) { return x === y; }
    // if they are regexps, they should exactly refer to same one (it is hard to better equality check on current ES)
    if (x instanceof RegExp) { return x === y; }
    if (x === y || x.valueOf() === y.valueOf()) { return true; }
    if (Array.isArray(x) && x.length !== y.length) { return false; }

    // if they are dates, they must had equal valueOf
    if (x instanceof Date) { return false; }

    // if they are strictly equal, they both need to be object at least
    if (!(x instanceof Object)) { return false; }
    if (!(y instanceof Object)) { return false; }

    // recursive object equality check
    var p = Object.keys(x);
    return Object.keys(y).every(function (i) { return p.indexOf(i) !== -1; }) &&
        p.every(function (i) { return objectEquals(x[i], y[i]); });
}


///////////////////////////////////////////////////////////////
/// The borrowed tests, run them by clicking "Run code snippet"
///////////////////////////////////////////////////////////////
var printResult = function (x) {
    if (x) { document.write('<div style="color: green;">Passed</div>'); }
    else { document.write('<div style="color: red;">Failed</div>'); }
};
var assert = { isTrue: function (x) { printResult(x); }, isFalse: function (x) { printResult(!x); } }
assert.isTrue(objectEquals(null,null));
assert.isFalse(objectEquals(null,undefined));
assert.isFalse(objectEquals(/abc/, /abc/));
assert.isFalse(objectEquals(/abc/, /123/));
var r = /abc/;
assert.isTrue(objectEquals(r, r));

assert.isTrue(objectEquals("hi","hi"));
assert.isTrue(objectEquals(5,5));
assert.isFalse(objectEquals(5,10));

assert.isTrue(objectEquals([],[]));
assert.isTrue(objectEquals([1,2],[1,2]));
assert.isFalse(objectEquals([1,2],[2,1]));
assert.isFalse(objectEquals([1,2],[1,2,3]));

assert.isTrue(objectEquals({},{}));
assert.isTrue(objectEquals({a:1,b:2},{a:1,b:2}));
assert.isTrue(objectEquals({a:1,b:2},{b:2,a:1}));
assert.isFalse(objectEquals({a:1,b:2},{a:1,b:3}));

assert.isTrue(objectEquals({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}},{1:{name:"mhc",age:28}, 2:{name:"arb",age:26}}));
assert.isFalse(objectEquals({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}},{1:{name:"mhc",age:28}, 2:{name:"arb",age:27}}));

Object.prototype.equals = function (obj) { return objectEquals(this, obj); };
var assertFalse = assert.isFalse,
    assertTrue = assert.isTrue;

assertFalse({}.equals(null));
assertFalse({}.equals(undefined));

assertTrue("hi".equals("hi"));
assertTrue(new Number(5).equals(5));
assertFalse(new Number(5).equals(10));
assertFalse(new Number(1).equals("1"));

assertTrue([].equals([]));
assertTrue([1,2].equals([1,2]));
assertFalse([1,2].equals([2,1]));
assertFalse([1,2].equals([1,2,3]));
assertTrue(new Date("2011-03-31").equals(new Date("2011-03-31")));
assertFalse(new Date("2011-03-31").equals(new Date("1970-01-01")));

assertTrue({}.equals({}));
assertTrue({a:1,b:2}.equals({a:1,b:2}));
assertTrue({a:1,b:2}.equals({b:2,a:1}));
assertFalse({a:1,b:2}.equals({a:1,b:3}));

assertTrue({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}}.equals({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}}));
assertFalse({1:{name:"mhc",age:28}, 2:{name:"arb",age:26}}.equals({1:{name:"mhc",age:28}, 2:{name:"arb",age:27}}));

var a = {a: 'text', b:[0,1]};
var b = {a: 'text', b:[0,1]};
var c = {a: 'text', b: 0};
var d = {a: 'text', b: false};
var e = {a: 'text', b:[1,0]};
var i = {
    a: 'text',
    c: {
        b: [1, 0]
    }
};
var j = {
    a: 'text',
    c: {
        b: [1, 0]
    }
};
var k = {a: 'text', b: null};
var l = {a: 'text', b: undefined};

assertTrue(a.equals(b));
assertFalse(a.equals(c));
assertFalse(c.equals(d));
assertFalse(a.equals(e));
assertTrue(i.equals(j));
assertFalse(d.equals(k));
assertFalse(k.equals(l));

// from comments on stackoverflow post
assert.isFalse(objectEquals([1, 2, undefined], [1, 2]));
assert.isFalse(objectEquals([1, 2, 3], { 0: 1, 1: 2, 2: 3 }));
assert.isFalse(objectEquals(new Date(1234), 1234));

// no two different function is equal really, they capture their context variables
// so even if they have same toString(), they won't have same functionality
var func = function (x) { return true; };
var func2 = function (x) { return true; };
assert.isTrue(objectEquals(func, func));
assert.isFalse(objectEquals(func, func2));
assert.isTrue(objectEquals({ a: { b: func } }, { a: { b: func } }));
assert.isFalse(objectEquals({ a: { b: func } }, { a: { b: func2 } }));


objectEquals([1,2,undefined],[1,2])रिटर्नtrue
रॉय टिंकर

objectEquals([1,2,3],{0:1,1:2,2:3})यह भी लौटाता है true- जैसे कोई प्रकार की जाँच नहीं है, केवल कुंजी / मूल्य जाँच है।
रॉय टिंकर

objectEquals(new Date(1234),1234)रिटर्नtrue
रॉय टिंकर

1
अगर (x.constructor; == y.constructor) {झूठी; } यह अलग-अलग खिड़कियों में दो 'नए स्ट्रिंग (' ए ') की तुलना करने पर टूट जाएगा। मूल्य समानता के लिए, आपको यह जांचना होगा कि क्या String.isString दोनों वस्तुओं पर है, तो एक ढीली समानता जांच 'a =>' का उपयोग करें।
त्रिवेंको

1
"मूल्य" समानता और "सख्त" समानता के बीच बहुत बड़ा अंतर है और उन्हें उसी तरह लागू नहीं किया जाना चाहिए। मूल्य समानता को बुनियादी संरचना से अलग, प्रकारों के बारे में परवाह नहीं करनी चाहिए, जो इन 4 में से एक है: 'ऑब्जेक्ट' (यानी कुंजी / मूल्य जोड़े का एक संग्रह), 'संख्या', 'स्ट्रिंग', या 'एरे'। बस। कुछ भी जो संख्या, स्ट्रिंग, या सरणी नहीं है, की तुलना कुंजी / मान जोड़े के एक सेट के रूप में की जानी चाहिए, भले ही निर्माता क्या है (क्रॉस-विंडो-सुरक्षित)। वस्तुओं की तुलना करते समय, संख्या की शाब्दिक संख्याओं और उदाहरणों के मूल्य को बराबर करें, लेकिन संख्याओं के साथ तालमेल न करें।
त्रिवेंको

50

यदि आप JSON लाइब्रेरी का उपयोग कर रहे हैं, तो आप JSON के रूप में प्रत्येक ऑब्जेक्ट को एन्कोड कर सकते हैं, फिर समानता के लिए परिणामी स्ट्रिंग्स की तुलना करें।

var obj1={test:"value"};
var obj2={test:"value2"};

alert(JSON.encode(obj1)===JSON.encode(obj2));

नोट: जबकि यह उत्तर कई मामलों में काम करेगा, क्योंकि कई लोगों ने टिप्पणियों में बताया है कि यह कई कारणों से समस्याग्रस्त है। बहुत अधिक सभी मामलों में आप एक अधिक मजबूत समाधान खोजना चाहेंगे।


91
दिलचस्प है, लेकिन मेरी राय में थोड़ा मुश्किल। उदाहरण के लिए, क्या आप 100% गारंटी दे सकते हैं कि वस्तु गुण हमेशा एक ही क्रम में उत्पन्न होंगे?
गुइडो

25
यह एक अच्छा सवाल है, और एक और उठाता है, जैसे कि अलग-अलग आदेशों में समान गुणों वाली दो वस्तुएं वास्तव में समान हैं या नहीं। आप क्या मतलब है पर निर्भर करता है, मुझे लगता है।
जोएल अनयर

11
ध्यान दें कि अधिकांश एन्कोडर और स्ट्रिंगर कार्यों को अनदेखा करते हैं और नॉन की तरह नॉनफिनिटी नंबरों को शून्य में बदल देते हैं।
स्टीफन बेलेंगर

4
मैं गुइडो से सहमत हूं, गुणों का क्रम महत्वपूर्ण है और इसकी गारंटी नहीं दी जा सकती। @JoelAnair, मुझे लगता है कि अलग-अलग आदेशों में समान गुणों वाली दो वस्तुओं को समान माना जाना चाहिए यदि गुणों का मूल्य समान है।
जुजेर अली

5
यह एक वैकल्पिक JSON स्ट्रिंगर के साथ काम कर सकता है , जो लगातार ऑब्जेक्ट कुंजी को सॉर्ट करता है।
रॉय टिंकर

40

लघु कार्यात्मक deepEqualकार्यान्वयन:

function deepEqual(x, y) {
  return (x && y && typeof x === 'object' && typeof y === 'object') ?
    (Object.keys(x).length === Object.keys(y).length) &&
      Object.keys(x).reduce(function(isEqual, key) {
        return isEqual && deepEqual(x[key], y[key]);
      }, true) : (x === y);
}

संपादित करें : संस्करण 2, जिब के सुझाव और ES6 तीर फ़ंक्शन का उपयोग कर:

function deepEqual(x, y) {
  const ok = Object.keys, tx = typeof x, ty = typeof y;
  return x && y && tx === 'object' && tx === ty ? (
    ok(x).length === ok(y).length &&
      ok(x).every(key => deepEqual(x[key], y[key]))
  ) : (x === y);
}

5
आप को सरल बनाने के reduceसाथ बदल सकते हैं every
jib

1
@nonkertompf यकीन है कि वह कर सकता था Object.keys(x).every(key => deepEqual(x[key], y[key])):।
जिब

2
यह तब विफल हो जाता है जब आप दो तारीखों की तुलना कर रहे होते हैं
ग्रेग

3
deepEqual ({}, []) सच लौटाता है
AlexMorley-Finch

3
हां, यदि आप इस तरह के कोने के मामले की देखभाल करते हैं, तो बदसूरत समाधान को बदलने : (x === y)के लिए है: (x === y && (x != null && y != null || x.constructor === y.constructor))
atmin

22

क्या आप परीक्षण करने की कोशिश कर रहे हैं कि क्या दो वस्तुएं समान हैं? अर्थात: उनके गुण बराबर हैं?

यदि यह मामला है, तो आप शायद इस स्थिति पर ध्यान देंगे:

var a = { foo : "bar" };
var b = { foo : "bar" };
alert (a == b ? "Equal" : "Not equal");
// "Not equal"

आपको ऐसा कुछ करना पड़ सकता है:

function objectEquals(obj1, obj2) {
    for (var i in obj1) {
        if (obj1.hasOwnProperty(i)) {
            if (!obj2.hasOwnProperty(i)) return false;
            if (obj1[i] != obj2[i]) return false;
        }
    }
    for (var i in obj2) {
        if (obj2.hasOwnProperty(i)) {
            if (!obj1.hasOwnProperty(i)) return false;
            if (obj1[i] != obj2[i]) return false;
        }
    }
    return true;
}

जाहिर है कि फ़ंक्शन काफी अनुकूलन के साथ कर सकता था, और गहरी जाँच करने की क्षमता (नेस्टेड ऑब्जेक्ट्स को संभालने के लिए var a = { foo : { fu : "bar" } }) : लेकिन आपको विचार मिलता है।

जैसा कि बताया गया है, आपको इसे अपने स्वयं के उद्देश्यों के लिए अनुकूलित करना पड़ सकता है, जैसे: विभिन्न वर्गों में "समान" की अलग-अलग परिभाषा हो सकती है। यदि आप केवल सादे वस्तुओं के साथ काम कर रहे हैं, तो उपरोक्त पर्याप्त हो सकता है, अन्यथा एक कस्टम MyClass.equals()फ़ंक्शन जाने का रास्ता हो सकता है।


यह एक लंबी विधि है लेकिन यह प्रत्येक वस्तु में गुणों के क्रम पर कोई धारणा बनाए बिना वस्तुओं का पूरी तरह से परीक्षण करता है।
४ins बजे briancollins081

22

यदि आपके पास एक गहरी प्रतिलिपि कार्य है, तो आप संपत्तियों के क्रम से मेल खाते हुए अभी भी उपयोग करने के लिए निम्न चाल का उपयोग कर सकते हैं JSON.stringify:

function equals(obj1, obj2) {
    function _equals(obj1, obj2) {
        return JSON.stringify(obj1)
            === JSON.stringify($.extend(true, {}, obj1, obj2));
    }
    return _equals(obj1, obj2) && _equals(obj2, obj1);
}

डेमो: http://jsfiddle.net/CU3vb/3/

दलील:

चूंकि obj1क्लोन के गुणों को एक-एक करके कॉपी किया जाता है, इसलिए क्लोन में उनके ऑर्डर को संरक्षित किया जाएगा। और जब obj2क्लोन के गुणों को कॉपी किया जाता है, क्योंकि पहले से मौजूद गुणों obj1को केवल अधिलेखित कर दिया जाएगा, क्लोन में उनके आदेश संरक्षित होंगे।


11
मुझे नहीं लगता कि ब्राउज़रों / इंजनों में ऑर्डर संरक्षण की गारंटी है।
जो लिस

@JoLiss उद्धरणों की आवश्यकता;) मुझे याद है कि कई ब्राउज़रों में इसका परीक्षण किया जा रहा है, जिससे लगातार परिणाम मिल रहे हैं। लेकिन निश्चित रूप से, कोई भी भविष्य के ब्राउज़र / इंजन में शेष व्यवहार की गारंटी नहीं दे सकता है। यह एक चाल है (जैसा कि पहले से ही जवाब में कहा जाता है) सबसे अच्छा है, और मेरा मतलब यह नहीं था कि वस्तुओं की तुलना करना एक निश्चित तरीका है।
एतेस गोराल

1
ज़रूर, यहाँ कुछ संकेत हैं: ECMAScript कल्पना कहती है कि वस्तु "अनियंत्रित" है ; और यह वर्तमान ब्राउज़रों पर वास्तविक विचलन व्यवहार के लिए उत्तर है।
जो लिस

2
@JoLiss इसके लिए धन्यवाद! लेकिन कृपया ध्यान दें कि मैं कभी भी कोड और संकलित वस्तु के बीच आदेश के संरक्षण का दावा नहीं कर रहा था। मैं उन संपत्तियों के ऑर्डर को संरक्षित करने का दावा कर रहा था जिनके मूल्य जगह-जगह मिलते हैं। मेरे समाधान के साथ यह महत्वपूर्ण था: संपत्ति मूल्यों को अधिलेखित करने के लिए एक मिश्रण का उपयोग करना। आम तौर पर कार्यान्वयन मानकर हैशमैप के कुछ प्रकारों का उपयोग करने का विकल्प चुनते हैं, केवल मानों को बदलने के लिए कुंजी के क्रम को संरक्षित करना चाहिए। यह वास्तव में यह है कि मैंने विभिन्न ब्राउज़रों में परीक्षण किया था।
एतेस गोराल

1
@AtesGoral: क्या इस बाधा को थोड़ा और अधिक स्पष्ट (बोल्डफेस, ...) करना संभव है। अधिकांश लोग बस इसके चारों ओर के पाठ को पढ़े बिना कॉपी-पेस्ट करते हैं ...
विलेम वैन ओन्सेम

21

Node.js में, आप इसके मूल का उपयोग कर सकते हैं require("assert").deepStrictEqual। अधिक जानकारी: http://nodejs.org/api/assert.html

उदाहरण के लिए:

var assert = require("assert");
assert.deepStrictEqual({a:1, b:2}, {a:1, b:3}); // will throw AssertionError

एक और उदाहरण जो रिटर्निंग त्रुटियों के बदले true/ falseवापसी करता है:

var assert = require("assert");

function deepEqual(a, b) {
    try {
      assert.deepEqual(a, b);
    } catch (error) {
      if (error.name === "AssertionError") {
        return false;
      }
      throw error;
    }
    return true;
};

Chaiयह सुविधा भी है। इसके मामले में, आप उपयोग करेंगे:var foo = { a: 1 }; var bar = { a: 1 }; expect(foo).to.deep.equal(bar); // true;
फोलुषो ओलादिपो

Node.js के कुछ संस्करण सेट error.nameहैं "AssertionError [ERR_ASSERTION]"। इस मामले में, अगर मैं बयान को बदलूंगा if (error.code === 'ERR_ASSERTION') {
नॉट नुड्सन

मुझे नहीं पता deepStrictEqualथा कि रास्ता तय करना है। मैं अपने दिमाग को यह जानने की कोशिश कर रहा strictEqualथा कि काम क्यों नहीं कर रहा है। बहुत खुबस।
नेटऑपरेटर विब्बी

19

ऑब्जेक्ट, एरे, स्ट्रिंग, इंट जैसे सभी चीजों की तुलना के लिए सबसे सरल और तार्किक समाधान ...

JSON.stringify({a: val1}) === JSON.stringify({a: val2})

ध्यान दें:

  • आप को बदलने के लिए की जरूरत है val1और val2अपने ऑब्जेक्ट के साथ
  • ऑब्जेक्ट के लिए, आपको दोनों साइड ऑब्जेक्ट के लिए पुनरावर्ती रूप से (कुंजी द्वारा) सॉर्ट करना होगा

6
मैं यह मान रहा हूं कि यह कई मामलों में काम नहीं करेगा क्योंकि वस्तुओं में कुंजियों का क्रम मायने नहीं रखता है - जब तक JSON.stringifyकि एक वर्णानुक्रम पुन: व्यवस्थित नहीं होता है? (जिसे मैं प्रलेखित नहीं पाया जा सकता ।)
ब्रैम वनरॉय

हाँ, आप सही हैं ... ऑब्जेक्ट के लिए, आपको दोनों साइड ऑब्जेक्ट्स के लिए पुनरावर्ती सॉर्ट करना होगा
प्रतीक भालोदिया

2
यह परिपत्र संदर्भ वाली वस्तुओं के लिए काम नहीं करता है
नैट-बिट इंट

13

मैं इस comparableफ़ंक्शन का उपयोग अपनी वस्तुओं की प्रतियां बनाने के लिए करता हूं जो JSON तुलनीय हैं:

var comparable = o => (typeof o != 'object' || !o)? o :
  Object.keys(o).sort().reduce((c, key) => (c[key] = comparable(o[key]), c), {});

// Demo:

var a = { a: 1, c: 4, b: [2, 3], d: { e: '5', f: null } };
var b = { b: [2, 3], c: 4, d: { f: null, e: '5' }, a: 1 };

console.log(JSON.stringify(comparable(a)));
console.log(JSON.stringify(comparable(b)));
console.log(JSON.stringify(comparable(a)) == JSON.stringify(comparable(b)));
<div id="div"></div>

परीक्षणों में काम आता है (अधिकांश परीक्षण रूपरेखाओं में एक isफ़ंक्शन होता है)। उदाहरण के लिए

is(JSON.stringify(comparable(x)), JSON.stringify(comparable(y)), 'x must match y');

यदि कोई अंतर पकड़ा जाता है, तो स्ट्रिंग लॉग हो जाती है, जिससे अंतर स्पॉट हो जाता है:

x must match y
got      {"a":1,"b":{"0":2,"1":3},"c":7,"d":{"e":"5","f":null}},
expected {"a":1,"b":{"0":2,"1":3},"c":4,"d":{"e":"5","f":null}}.

1
अच्छा विचार (मेरे मामले में वस्तुओं की तुलना एक मुख्य कुंजी / मूल्य-जोड़े, कोई विशेष चीजों से नहीं की जा सकती)
mech

10

एक कार्यात्मक शैली दृष्टिकोण का उपयोग कर ES6 / ES2015 में हेयर्स का समाधान:

const typeOf = x => 
  ({}).toString
      .call(x)
      .match(/\[object (\w+)\]/)[1]

function areSimilar(a, b) {
  const everyKey = f => Object.keys(a).every(f)

  switch(typeOf(a)) {
    case 'Array':
      return a.length === b.length &&
        everyKey(k => areSimilar(a.sort()[k], b.sort()[k]));
    case 'Object':
      return Object.keys(a).length === Object.keys(b).length &&
        everyKey(k => areSimilar(a[k], b[k]));
    default:
      return a === b;
  }
}

यहां डेमो उपलब्ध है


ऑब्जेक्ट कुंजियों का क्रम बदल गया है तो काम नहीं करता है।
इसहाक पाक

9

मुझे नहीं पता कि किसी को भी इस तरह के कुछ भी पोस्ट किया है, लेकिन यहाँ एक समारोह मैं वस्तु समानता के लिए जाँच करने के लिए बनाया है।

function objectsAreEqual(a, b) {
  for (var prop in a) {
    if (a.hasOwnProperty(prop)) {
      if (b.hasOwnProperty(prop)) {
        if (typeof a[prop] === 'object') {
          if (!objectsAreEqual(a[prop], b[prop])) return false;
        } else {
          if (a[prop] !== b[prop]) return false;
        }
      } else {
        return false;
      }
    }
  }
  return true;
}

इसके अलावा, यह पुनरावर्ती है, इसलिए यह गहरी समानता के लिए भी जांच कर सकता है, यदि आप इसे कहते हैं।


छोटा सुधार: a और b में प्रत्येक प्रॉप्स से गुजरने से पहले इस चेक को जोड़ें यदि (Object.getOwnPropertyNN (a) .length! = Object.getOwnnperpertyNames (b) .length वापस लौटें
Hith

1
यह स्पष्ट है कि उचित समानता चेकर पुनरावर्ती होना चाहिए। मुझे लगता है कि ऐसे पुनरावर्ती उत्तरों में से एक सही उत्तर होना चाहिए। स्वीकृत उत्तर कोड नहीं देता है और यह मदद नहीं करता है
canbax

9

NodeJS का उपयोग करने वाले लोगों के लिए, isDeepStrictEqualदेशी यूटिल लाइब्रेरी पर एक सुविधाजनक विधि है जो इसे प्राप्त कर सकती है।

const util = require('util');

const obj1 = {
  foo: "bar",
  baz: [1, 2]
};

const obj2 = {
  foo: "bar",
  baz: [1, 2]
};


obj1 == obj2 // false
util.isDeepStrictEqual(obj1, obj2) // true

https://nodejs.org/api/util.html#util_util_isdeepstrictequal_val1_val2


इसका प्रदर्शन अच्छा माना जाता है। कोई चिंता नहीं। यहां तक ​​कि मैं इसे जटिल परिदृश्यों में भी उपयोग करता हूं। जब हम इसका उपयोग करते हैं तो हमें चिंता करने की ज़रूरत नहीं है यदि वस्तु की संपत्ति वस्तु या सरणी को प्रभावित कर रही है। Json.Stringify इसे वैसे भी स्ट्रिंग बनाता है और जावास्क्रिप्ट में तारों की तुलना एक बड़ी बात नहीं है
ट्रिकऑट्रेट

6

ES6: न्यूनतम कोड मैं इसे प्राप्त कर सकता हूं, यह है। यह सभी वस्तुओं को कठोर करके पुनरावर्ती रूप से गहरी तुलना करता है, केवल सीमा कोई विधि नहीं है या प्रतीकों की तुलना नहीं की जाती है।

const compareObjects = (a, b) => { 
  let s = (o) => Object.entries(o).sort().map(i => { 
     if(i[1] instanceof Object) i[1] = s(i[1]);
     return i 
  }) 
  return JSON.stringify(s(a)) === JSON.stringify(s(b))
}

console.log(compareObjects({b:4,a:{b:1}}, {a:{b:1},b:4}));


यह एक पूरी तरह से कार्यात्मक उत्तर है, धन्यवाद @ Adriano Spadoni। क्या आप जानते हैं कि मैं उस कुंजी / विशेषता को कैसे प्राप्त कर सकता हूं जिसे संशोधित किया गया था? धन्यवाद,
डिजाइली

1
hi @digital, अगर आपको ज़रूरत है कि कौन सी कुंजियाँ अलग हैं, तो यह आदर्श कार्य नहीं है। अन्य उत्तर की जाँच करें और ऑब्जेक्ट के माध्यम से एक लूप के साथ उपयोग करें।
एड्रियानो स्पैडोनी

5

आप _.isEqual(obj1, obj2)underscore.js लाइब्रेरी से उपयोग कर सकते हैं ।

यहाँ एक उदाहरण है:

var stooge = {name: 'moe', luckyNumbers: [13, 27, 34]};
var clone  = {name: 'moe', luckyNumbers: [13, 27, 34]};
stooge == clone;
=> false
_.isEqual(stooge, clone);
=> true

यहां से आधिकारिक दस्तावेज देखें: http://underscorejs.org/#isEqual


5

यह मानते हुए कि ऑब्जेक्ट में गुणों का क्रम नहीं बदला गया है।

JSON.stringify () गहरी और गैर-गहरी दोनों प्रकार की वस्तुओं के लिए काम करता है, प्रदर्शन पहलुओं के बारे में निश्चित नहीं:

var object1 = {
  key: "value"
};

var object2 = {
  key: "value"
};

var object3 = {
  key: "no value"
};

console.log('object1 and object2 are equal: ', JSON.stringify(object1) === JSON.stringify(object2));

console.log('object2 and object3 are equal: ', JSON.stringify(object2) === JSON.stringify(object3));


1
यह वह नहीं करता है जो ओपी चाहता है, क्योंकि यह केवल मेल खाएगा यदि दोनों वस्तुओं में सभी समान कुंजी हैं, जो वे कहते हैं कि वे नहीं करेंगे। इसके लिए चाबियों का भी उसी क्रम में होना आवश्यक है, जो वास्तव में उचित भी नहीं है।
स्पीडऑफ राउंड

1
अलग-अलग क्रम में क्या गुण हैं ??? नहीं एक अच्छी विधि
विशाल सकारिया

4

इस मुद्दे का एक सरल समाधान है कि कई लोगों को एहसास नहीं है कि JSON तार (प्रति वर्ण) को सॉर्ट करना है। यह भी आम तौर पर यहाँ वर्णित अन्य समाधानों की तुलना में तेज़ है:

function areEqual(obj1, obj2) {
    var a = JSON.stringify(obj1), b = JSON.stringify(obj2);
    if (!a) a = '';
    if (!b) b = '';
    return (a.split('').sort().join('') == b.split('').sort().join(''));
}

इस विधि के बारे में एक और उपयोगी बात यह है कि आप JSON.stringify फ़ंक्शन ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) में "प्रतिकृति" फ़ंक्शन पास करके तुलनाओं को फ़िल्टर कर सकते हैं। / stringify # Example_of_using_replacer_parameter )। निम्नलिखित केवल सभी ऑब्जेक्ट कुंजी की तुलना करेंगे जिन्हें "derp" नाम दिया गया है:

function areEqual(obj1, obj2, filter) {
    var a = JSON.stringify(obj1, filter), b = JSON.stringify(obj2, filter);
    if (!a) a = '';
    if (!b) b = '';
    return (a.split('').sort().join('') == b.split('').sort().join(''));
}
var equal = areEqual(obj1, obj2, function(key, value) {
    return (key === 'derp') ? value : undefined;
});

1
ओह, मैं भी भूल गया था, लेकिन फ़ंक्शन को पहले परीक्षण ऑब्जेक्ट द्वारा बराबर किया जा सकता है और यदि वे समान वस्तु हैं तो जल्दी से जल्दी झुकेंगे: अगर (obj1 === obj2) वापस लौटें;
183 बजे th317erd

11
areEqual({a: 'b'}, {b: 'a'})trueतब मिलता है
ओकेम

हाँ, मुझे यह महसूस करने के बाद कि इस "समाधान" में समस्याएं हैं। यह वास्तव में ठीक से काम करने के लिए छँटाई एल्गोरिथ्म में थोड़ा और काम करने की आवश्यकता है।
th317erd

4

बस कुछ es6 सुविधाओं का उपयोग करते हुए तुलना करने वाली वस्तुओं के मेरे संस्करण में योगदान करना चाहता था। यह एक आदेश को ध्यान में नहीं रखता है। सभी को परिवर्तित करने के बाद अगर / ternary के लिए मैं निम्नलिखित के साथ आया हूँ:

function areEqual(obj1, obj2) {

    return Object.keys(obj1).every(key => {

            return obj2.hasOwnProperty(key) ?
                typeof obj1[key] === 'object' ?
                    areEqual(obj1[key], obj2[key]) :
                obj1[key] === obj2[key] :
                false;

        }
    )
}

3

पोस्ट किया गया था की तुलना में अधिक सामान्य वस्तु तुलना समारोह की जरूरत है, मैं निम्नलिखित पकाया। आलोचकों की सराहना की ...

Object.prototype.equals = function(iObj) {
  if (this.constructor !== iObj.constructor)
    return false;
  var aMemberCount = 0;
  for (var a in this) {
    if (!this.hasOwnProperty(a))
      continue;
    if (typeof this[a] === 'object' && typeof iObj[a] === 'object' ? !this[a].equals(iObj[a]) : this[a] !== iObj[a])
      return false;
    ++aMemberCount;
  }
  for (var a in iObj)
    if (iObj.hasOwnProperty(a))
      --aMemberCount;
  return aMemberCount ? false : true;
}

2
मैं इस के एक बदलाव का उपयोग कर समाप्त हो गया। सदस्यों की गिनती के विचार के लिए धन्यवाद!
नैट्स

2
संशोधन के बारे में बहुत सावधान रहें Object.prototype- अधिकांश मामलों में यह सलाह नहीं दी जाती है (उदाहरण के लिए, सभी लूपों में दिखाई देते हैं। उदाहरण के लिए)। शायद विचार करें Object.equals = function(aObj, bObj) {...}?
रॉय टिंकर

3

यदि आप JSON ऑब्जेक्ट्स की तुलना कर रहे हैं, तो आप https://github.com/mirek/node-rus-diff का उपयोग कर सकते हैं

npm install rus-diff

उपयोग:

a = {foo:{bar:1}}
b = {foo:{bar:1}}
c = {foo:{bar:2}}

var rusDiff = require('rus-diff').rusDiff

console.log(rusDiff(a, b)) // -> false, meaning a and b are equal
console.log(rusDiff(a, c)) // -> { '$set': { 'foo.bar': 2 } }

यदि दो ऑब्जेक्ट अलग हैं, तो {$rename:{...}, $unset:{...}, $set:{...}}ऑब्जेक्ट की तरह एक MongoDB संगत है।


3

मैंने उसी समस्या का सामना किया और अपना समाधान लिखने का फैसला किया। लेकिन क्योंकि मैं वस्तुओं और इसके विपरीत एरर्स की तुलना करना चाहता हूं, इसलिए मैंने एक सामान्य समाधान तैयार किया है। मैंने फ़ंक्शंस को प्रोटोटाइप में जोड़ने का फैसला किया, लेकिन कोई भी आसानी से स्टैंडअलोन फ़ंक्शंस को फिर से लिख सकता है। यहाँ कोड है:

Array.prototype.equals = Object.prototype.equals = function(b) {
    var ar = JSON.parse(JSON.stringify(b));
    var err = false;
    for(var key in this) {
        if(this.hasOwnProperty(key)) {
            var found = ar.find(this[key]);
            if(found > -1) {
                if(Object.prototype.toString.call(ar) === "[object Object]") {
                    delete ar[Object.keys(ar)[found]];
                }
                else {
                    ar.splice(found, 1);
                }
            }
            else {
                err = true;
                break;
            }
        }
    };
    if(Object.keys(ar).length > 0 || err) {
        return false;
    }
    return true;
}

Array.prototype.find = Object.prototype.find = function(v) {
    var f = -1;
    for(var i in this) {
        if(this.hasOwnProperty(i)) {
            if(Object.prototype.toString.call(this[i]) === "[object Array]" || Object.prototype.toString.call(this[i]) === "[object Object]") {
                if(this[i].equals(v)) {
                    f = (typeof(i) == "number") ? i : Object.keys(this).indexOf(i);
                }
            }
            else if(this[i] === v) {
                f = (typeof(i) == "number") ? i : Object.keys(this).indexOf(i);
            }
        }
    }
    return f;
}

यह एल्गोरिथ्म दो भागों में विभाजित है; समतुल्य एक सरणी / वस्तु में एक संपत्ति के संख्यात्मक सूचकांक को खोजने के लिए खुद को और एक कार्य करता है। खोज फ़ंक्शन को केवल इसलिए आवश्यक है क्योंकि इंडेक्सोफ़ केवल संख्या और तार और कोई ऑब्जेक्ट नहीं ढूंढता है।

कोई इसे इस तरह कह सकता है:

({a: 1, b: "h"}).equals({a: 1, b: "h"});

फ़ंक्शन या तो सही या गलत देता है, इस मामले में सच है। एल्गोरिथ्म ए एल बहुत जटिल वस्तुओं के बीच तुलना की अनुमति देता है:

({a: 1, b: "hello", c: ["w", "o", "r", "l", "d", {answer1: "should be", answer2: true}]}).equals({b: "hello", a: 1, c: ["w", "d", "o", "r", {answer1: "should be", answer2: true}, "l"]})

ऊपरी उदाहरण सच हो जाएगा, यहां तक ​​कि गुणों का एक अलग क्रम है। देखने के लिए एक छोटा सा विवरण: यह कोड एक ही प्रकार के दो चर की भी जाँच करता है, इसलिए "3" 3 के समान नहीं है।


3

मैं स्पेगेटी कोड के उत्तर देखता हूं। किसी भी तीसरे पक्ष के काम का उपयोग किए बिना, यह बहुत आसान है।

सबसे पहले दो प्रमुख वस्तुओं को उनके प्रमुख नामों के आधार पर क्रमबद्ध करें।

let objectOne = { hey, you }
let objectTwo = { you, hey }

// If you really wanted you could make this recursive for deep sort.
const sortObjectByKeyname = (objectToSort) => {
    return Object.keys(objectToSort).sort().reduce((r, k) => (r[k] = objectToSort[k], r), {});
}

let objectOne = sortObjectByKeyname(objectOne)
let objectTwo = sortObjectByKeyname(objectTwo)

फिर उनकी तुलना करने के लिए बस एक स्ट्रिंग का उपयोग करें।

JSON.stringify(objectOne) === JSON.stringify(objectTwo)

यह भी गहरी प्रतिलिपि के लिए काम नहीं करता है, इसमें केवल एक पुनरावृत्ति गहराई है।
अरस

मुझे लगता है कि @andras का मतलब है कि आपको नेस्टेड ऑब्जेक्ट्स की कुंजी को पुन: क्रमबद्ध करने की आवश्यकता है।
डेवी लीमा

2

मैं हैशिंग या क्रमांकन (JSON समाधान सुझाव के अनुसार) के खिलाफ सलाह दूंगा। यदि आपको दो वस्तुओं के बराबर होने पर परीक्षण करने की आवश्यकता है, तो आपको यह परिभाषित करने की आवश्यकता है कि बराबरी का क्या अर्थ है। यह हो सकता है कि दोनों ऑब्जेक्ट में सभी डेटा सदस्य मेल खाते हों, या यह हो सकता है कि मेमोरी लोकेशन मैच होना चाहिए (मतलब दोनों वैरिएबल एक ही ऑब्जेक्ट को मेमोरी में रेफर करते हैं), या यह हो सकता है कि प्रत्येक ऑब्जेक्ट में केवल एक डेटा सदस्य मैच होना चाहिए।

हाल ही में मैंने एक ऑब्जेक्ट विकसित किया है जिसका निर्माता एक नई आईडी बनाता है (1 से शुरू और 1 से वृद्धि) हर बार एक उदाहरण बनाया जाता है। इस ऑब्जेक्ट में एक आइसक्वाल फ़ंक्शन होता है जो उस आईडी वैल्यू की तुलना किसी अन्य ऑब्जेक्ट की आईडी वैल्यू के साथ करता है और यदि वे मेल खाते हैं तो सही हो जाते हैं।

उस मामले में मैंने "बराबर" को परिभाषित किया, जिसका अर्थ आईडी मान से मेल खाता है। यह देखते हुए कि प्रत्येक उदाहरण में एक विशिष्ट आईडी है, इसका उपयोग इस विचार को लागू करने के लिए किया जा सकता है कि मिलान करने वाले ऑब्जेक्ट भी उसी मेमोरी स्थान पर कब्जा कर लेते हैं। हालांकि यह जरूरी नहीं है।


2

यह दो वस्तुओं के बराबर विचार करने के लिए उपयोगी है यदि उनके पास सभी संपत्तियों के लिए सभी समान मूल्य हैं और सभी नेस्टेड ऑब्जेक्ट और सरणियों के लिए पुनरावर्ती हैं। मैं निम्नलिखित दो वस्तुओं को भी समान मानता हूं:

var a = {p1: 1};
var b = {p1: 1, p2: undefined};

इसी तरह, सरणियों में "लापता" तत्व और अपरिभाषित तत्व हो सकते हैं। मैं उन लोगों के साथ भी ऐसा ही व्यवहार करूंगा:

var c = [1, 2];
var d = [1, 2, undefined];

एक फ़ंक्शन जो समानता की इस परिभाषा को लागू करता है:

function isEqual(a, b) {
    if (a === b) {
        return true;
    }

    if (generalType(a) != generalType(b)) {
        return false;
    }

    if (a == b) {
        return true;
    }

    if (typeof a != 'object') {
        return false;
    }

    // null != {}
    if (a instanceof Object != b instanceof Object) {
        return false;
    }

    if (a instanceof Date || b instanceof Date) {
        if (a instanceof Date != b instanceof Date ||
            a.getTime() != b.getTime()) {
            return false;
        }
    }

    var allKeys = [].concat(keys(a), keys(b));
    uniqueArray(allKeys);

    for (var i = 0; i < allKeys.length; i++) {
        var prop = allKeys[i];
        if (!isEqual(a[prop], b[prop])) {
            return false;
        }
    }
    return true;
}

सोर्स कोड (हेल्पर फ़ंक्शंस, जनरल टाइप और यूनिकअरे सहित): यूनिट टेस्ट और टेस्ट रनर


2

मैं इस समारोह के साथ निम्नलिखित धारणाएं बना रहा हूं:

  1. आप उन वस्तुओं को नियंत्रित करते हैं, जिनकी आप तुलना कर रहे हैं और आपके पास केवल आदिम मूल्य हैं (यानी नेस्टेड ऑब्जेक्ट्स, फ़ंक्शन आदि नहीं हैं)।
  2. आपके ब्राउज़र में Object.keys का समर्थन है ।

इसे एक साधारण रणनीति के प्रदर्शन के रूप में माना जाना चाहिए।

/**
 * Checks the equality of two objects that contain primitive values. (ie. no nested objects, functions, etc.)
 * @param {Object} object1
 * @param {Object} object2
 * @param {Boolean} [order_matters] Affects the return value of unordered objects. (ex. {a:1, b:2} and {b:2, a:1}).
 * @returns {Boolean}
 */
function isEqual( object1, object2, order_matters ) {
    var keys1 = Object.keys(object1),
        keys2 = Object.keys(object2),
        i, key;

    // Test 1: Same number of elements
    if( keys1.length != keys2.length ) {
        return false;
    }

    // If order doesn't matter isEqual({a:2, b:1}, {b:1, a:2}) should return true.
    // keys1 = Object.keys({a:2, b:1}) = ["a","b"];
    // keys2 = Object.keys({b:1, a:2}) = ["b","a"];
    // This is why we are sorting keys1 and keys2.
    if( !order_matters ) {
        keys1.sort();
        keys2.sort();
    }

    // Test 2: Same keys
    for( i = 0; i < keys1.length; i++ ) {
        if( keys1[i] != keys2[i] ) {
            return false;
        }
    }

    // Test 3: Values
    for( i = 0; i < keys1.length; i++ ) {
        key = keys1[i];
        if( object1[key] != object2[key] ) {
            return false;
        }
    }

    return true;
}

2

यह उपरोक्त सभी के लिए एक अतिरिक्त है, प्रतिस्थापन नहीं है। यदि आपको अतिरिक्त पुनरावर्ती मामलों की जांच करने की आवश्यकता के बिना वस्तुओं की तुलना में तेजी से उथले करने की आवश्यकता है। यहाँ एक शॉट है।

इसके लिए यह तुलना करता है: 1) स्वयं के गुणों की संख्या की समानता, 2) प्रमुख नामों की समानता, 3) यदि bCompareValues ​​== सच है, संबंधित संपत्ति मूल्यों की समानता और उनके प्रकार (ट्रिपल समानता)

var shallowCompareObjects = function(o1, o2, bCompareValues) {
    var s, 
        n1 = 0,
        n2 = 0,
        b  = true;

    for (s in o1) { n1 ++; }
    for (s in o2) { 
        if (!o1.hasOwnProperty(s)) {
            b = false;
            break;
        }
        if (bCompareValues && o1[s] !== o2[s]) {
            b = false;
            break;
        }
        n2 ++;
    }
    return b && n1 == n2;
}

2

सरल कुंजी / मूल्य जोड़े ऑब्जेक्ट इंस्टेंस के लिए कुंजियों की तुलना करने के लिए, मैं उपयोग करता हूं:

function compareKeys(r1, r2) {
    var nloops = 0, score = 0;
    for(k1 in r1) {
        for(k2 in r2) {
            nloops++;
            if(k1 == k2)
                score++; 
        }
    }
    return nloops == (score * score);
};

एक बार कुंजियों की तुलना करने के बाद, एक साधारण अतिरिक्त for..inलूप पर्याप्त है।

जटिलता हे (N * N) के साथ N की कुंजी की संख्या है।

मुझे आशा है कि / अनुमान वस्तुओं मैं 1000 से अधिक संपत्ति पकड़ नहीं होगा परिभाषित ...


2

मुझे पता है कि यह थोड़ा पुराना है, लेकिन मैं एक समाधान जोड़ना चाहूंगा कि मैं इस समस्या के लिए आया हूं। मेरे पास एक वस्तु थी और मैं जानना चाहता था कि इसका डेटा कब बदला गया। "Object.observe के समान कुछ" और मैंने जो किया वह था:

function checkObjects(obj,obj2){
   var values = [];
   var keys = [];
   keys = Object.keys(obj);
   keys.forEach(function(key){
      values.push(key);
   });
   var values2 = [];
   var keys2 = [];
   keys2 = Object.keys(obj2);
   keys2.forEach(function(key){
      values2.push(key);
   });
   return (values == values2 && keys == keys2)
}

मूल्यों और कुंजियों की तुलना करने के लिए यह यहां डुप्लिकेट किया जा सकता है और सरणियों का एक और सेट बना सकता है। यह बहुत सरल है क्योंकि वे अब सरणियाँ हैं और झूठी वापस आएँगी यदि वस्तुओं के अलग-अलग आकार हैं।


1
यह हमेशा लौटेगा false, क्योंकि सरणियों की तुलना मूल्य से नहीं की जाती है, जैसे [1,2] != [1,2]
जिब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.