দুটি জাভাস্ক্রিপ্ট অবজেক্টের জন্য সাম্যতা কীভাবে নির্ধারণ করবেন?


669

একটি কঠোর সাম্য অপারেটর আপনাকে বলবে যে দুটি বস্তুর প্রকার সমান কিনা । তবে, জাভাতে হ্যাশ কোড মানের মতো দুটি বস্তু সমান কিনা তা বলার উপায় আছে ?

স্ট্যাক ওভারফ্লো প্রশ্ন জাভাস্ক্রিপ্টে কোনও ধরণের হ্যাশকোড ফাংশন রয়েছে? এই প্রশ্নের অনুরূপ, তবে আরও একাডেমিক উত্তর প্রয়োজন। উপরের দৃশ্যটি দেখায় যে এটির কেন প্রয়োজনীয় হবে এবং আমি ভাবছি যে এর কোনও সমতুল্য সমাধান আছে কিনা ।


3
এছাড়াও এই প্রশ্নটি দেখুন stackoverflow.com/q/1068834/1671639
প্রবীণ

37
উল্লেখ্য, জাভা এমনকি a.hashCode() == b.hashCode()নেই না যে পরোক্ষভাবে aসমান b। এটি একটি প্রয়োজনীয় শর্ত, পর্যাপ্ত শর্ত নয়।
হেইনজি

দয়া করে এই প্রশ্নাগুলি দেখুন: স্ট্যাকওভারফ্লো.com
প্রশ্নগুলি

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মাইক্লাসের কোনও দুটি উদাহরণ সমান, কেবল aএবং bগুরুত্বপূর্ণ কিনা তা নির্ধারণ করা সত্যই গুরুত্বপূর্ণ নয় । কিছু ক্ষেত্রে cউদাহরণগুলির মধ্যে পৃথক হতে পারে এবং তুলনার সময় তাৎপর্যপূর্ণ নয়।

নোট করুন এই সমস্যাটি প্রযোজ্য হবে যখন সদস্যরা নিজেরাই কোনও প্রকারের উদাহরণ হতে পারে এবং এগুলির প্রত্যেকেরই সমতা নির্ধারণের একটি মাধ্যম থাকা প্রয়োজন।

আরও জটিল বিষয় হ'ল জাভাস্ক্রিপ্টে ডেটা এবং পদ্ধতির মধ্যে পার্থক্য ঝাপসা।

কোনও অবজেক্ট এমন একটি পদ্ধতি উল্লেখ করতে পারে যা ইভেন্ট হ্যান্ডলার হিসাবে ডাকা হয় এবং এটি সম্ভবত এটির 'মান অবস্থার' অংশ হিসাবে বিবেচিত হবে না। অন্য কোনও অবজেক্টকে এমন একটি ফাংশন নির্ধারণ করা যেতে পারে যা একটি গুরুত্বপূর্ণ গণনা সম্পাদন করে এবং এর ফলে এই উদাহরণটি অন্যদের থেকে আলাদা করে তোলে কারণ এটি একটি ভিন্ন ফাংশনকে উল্লেখ করে।

এমন কোনও জিনিসের বিষয়ে কী কী এর বিদ্যমান প্রোটোটাইপ পদ্ধতিগুলির মধ্যে একটি অন্য ফাংশন দ্বারা ওভাররাইড করা হয়? এটি এখনও অন্য উদাহরণের সমান হিসাবে বিবেচিত হতে পারে যে এটি অন্যথায় অভিন্ন? এই প্রশ্নের উত্তর কেবলমাত্র প্রতিটি ধরণের জন্য নির্দিষ্ট ক্ষেত্রে দেওয়া যেতে পারে।

যেমনটি আগেই বলা হয়েছে, ব্যতিক্রমটি কঠোরভাবে টাইপলেস অবজেক্ট হবে। এক্ষেত্রে একমাত্র বুদ্ধিমান পছন্দ হ'ল প্রতিটি সদস্যের পুনরাবৃত্ত এবং পুনরাবৃত্ত তুলনা। তারপরেও একজনকে জিজ্ঞাসা করতে হবে যে কোনও ফাংশনের 'মান' কী?


175
আপনি যদি আন্ডারস্কোর ব্যবহার করে থাকেন তবে আপনি কেবল করতে পারেন_.isEqual(obj1, obj2);
2113

12
@ হর্ষ, উত্তরটি কোনও সমাধান দিতে ব্যর্থ হয়েছে কারণ এর কোনওই নেই। এমনকি জাভাতেও, সাম্যের তুলনা বাছাই করার জন্য এবং রূপটি সঠিকভাবে প্রয়োগ করাতে কোন রূপালী বুলেট নেই .equalsতাত্পর্যপূর্ণ নয়, এজন্য কার্যকর জাভাতে এই জাতীয় বিষয় উত্সর্গীকৃত রয়েছে ।
lcn

3
@ কুমার হর্ষ, যা দুটি বস্তুকে সমান করে তোলে তা অত্যন্ত প্রয়োগ নির্দিষ্ট; কোনও জিনিসের প্রতিটি সম্পত্তি অগত্যা বিবেচনায় নেওয়া উচিত নয়, সুতরাং কোনও বস্তুর প্রতিটি সম্পত্তিকে জোর করে চাপিয়ে দেওয়া কোনও ठोस সমাধান নয়।
sethro

googled javascript equality object, tl পেয়েছে; Dr উত্তর, @ Chovy মন্তব্য থেকে ওয়ান-লাইনার নিয়েছে। আপনাকে ধন্যবাদ
Andrea

যদি কৌণিক ব্যবহার করা হয় তবে আপনার কাছে রয়েছেangular.equals
বোটকোডার

506

চাকা পুনরুদ্ধার কেন? দিন Lodash ব্যবহার করে দেখুন। এটিতে ইস্কুল () এর মতো বেশ কয়েকটি আবশ্যক ফাংশন থাকতে হবে ।

_.isEqual(object, other);

এটি ব্রাউজারে উপলভ্য থাকলে ECMAScript 5 এবং নেটিভ অপ্টিমাইজেশন ব্যবহার করে - এই পৃষ্ঠার অন্যান্য উদাহরণগুলির মতো - প্রতিটি মূল্যের মান পরীক্ষা করতে বাধ্য করবে ।

নোট: পূর্বে এই উত্তর সুপারিশ Underscore.js কিন্তু lodash সংশোধন বাগ পাওয়া এবং দৃঢ়তা সমস্যা অ্যাড্রেসিং একটি ভাল কাজ করেছেন।


27
ইন্ডসকোরের ইস্কুল ফাংশনটি খুব সুন্দর (তবে এটি ব্যবহারের জন্য আপনাকে তাদের লাইব্রেরিতে টানতে হবে - প্রায় 3 কে জিপিআইপি)।
mckoss

29
আর কি কি আন্ডারস্কোর আপনাকে দেয় তা যদি আপনি তাকান তবে আপনাকে এটিকে টেনে আনতে আফসোস হবে না
পান্ডাউড

6
নির্ভরতা হিসাবে আন্ডারস্কোর রাখার সামর্থ্য না থাকলেও, ইস্কাল ফাংশনটি টানুন, লাইসেন্সের প্রয়োজনীয়তাগুলি পূরণ করুন এবং এগিয়ে যান। এটি স্ট্যাকওভারফ্লোতে উল্লিখিত এখন পর্যন্ত সর্বাধিক বিস্তৃত সমতা পরীক্ষা।
ডেল অ্যান্ডারসন

7
এখানে লোড্যাশ নামে একটি অ্যান্ডসকোরের কাঁটাচামচ রয়েছে এবং লেখক সেই মত ধারাবাহিকতার বিষয়ে খুব উদ্বিগ্ন। লোড্যাশ দিয়ে পরীক্ষা করুন এবং দেখুন কী পান।
CoolAJ86

6
আপনি যদি পুরো লাইব্রেরিটি না চান তবে @ এমকোসস আপনি স্ট্যান্ডেলোন মডিউলটি ব্যবহার করতে পারেন npmjs.com/package/lodash.isequal
রব ফক্স

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 স্ট্রিংয়ে রূপান্তর করা যায়, তবে এটি একটি সমান () ফাংশনটিকে সহজ করে তোলে।
স্কটগুলি

3
@ স্কটস সবসময় না। জেএসএন-তে বস্তু রূপান্তর করা এবং স্ট্রিংগুলির সাথে তুলনা করা আঁট লুপগুলিতে জটিল বস্তুর জন্য গুণগতভাবে নিবিড় হয়ে উঠতে পারে। সাধারণ বস্তুগুলির জন্য এটি সম্ভবত খুব বেশি গুরুত্ব দেয় না, তবে বাস্তবে এটি আপনার নির্দিষ্ট পরিস্থিতির উপর নির্ভর করে। একটি সঠিক সমাধান বস্তুর আইডি তুলনা বা প্রতিটি সম্পত্তি যাচাই করার মতো সহজ হতে পারে, তবে এর নির্ভুলতা পুরোপুরি সমস্যা ডোমেন দ্বারা নির্ধারিত হয়।
ড্যানিয়েল এক্স মুর

আমরা কি পাশাপাশি ডেটা টাইপ তুলনা করা উচিত ?! other.rank === this.rank && અન્ય.সুট === এই.সুট;
devsathish

1
@ দেবস্যাথিশ সম্ভবত নেই। জাভাস্ক্রিপ্টে প্রকারগুলি বেশ দ্রুত এবং আলগা হয় তবে আপনার ডোমেইনের প্রকারগুলি যদি গুরুত্বপূর্ণ হয় তবে আপনি প্রকারগুলিও পরীক্ষা করতে চাইতে পারেন।
ড্যানিয়েল এক্স মুর

7
@ স্কটস জেএসএনে রূপান্তর করার ক্ষেত্রে অন্যান্য সমস্যা হ'ল স্ট্রিংয়ের বৈশিষ্ট্যগুলির ক্রমটি উল্লেখযোগ্য হয়ে ওঠে। {x:1, y:2}! =={y:2, x:1}
স্টিজন ডি উইট

81

আপনি কাজ করেন, তাহলে AngularJS , angular.equalsফাংশন যদি দুটি বস্তুর সমান নির্ধারণ করা হবে। ইন Ember.js ব্যবহার isEqual

  • angular.equals- এই পদ্ধতিতে আরও জন্য ডক্স বা উত্স দেখুন। এটি অ্যারেতেও গভীর তুলনা করে।
  • এমবার.জেএস 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

এটি আমার সংস্করণ। এটি 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
if (x.constructor! == y.constructor) false মিথ্যা ফিরিয়ে দিন; Different বিভিন্ন উইন্ডোতে দুটি 'নতুন স্ট্রিং (' এ ')' তুলনা করার সময় এটি ভেঙে যায়। মান সমতার জন্য, আপনাকে উভয় বস্তুতে স্ট্রিং.আইএসআর স্ট্রিং কিনা তা পরীক্ষা করে দেখতে হবে, তারপরে একটি aিলে .ালা সমতা পরীক্ষা করতে হবে 'a == খ'।
ট্রায়ঙ্কো

1
"মান" সমতা এবং "কঠোর" সাম্যের মধ্যে একটি বিশাল পার্থক্য রয়েছে এবং সেগুলি একইভাবে প্রয়োগ করা উচিত নয়। মান কাঠামোটি মূল কাঠামো বাদ দিয়ে প্রকারের বিষয়ে চিন্তা করা উচিত নয়, যা এই 4 টির মধ্যে একটি: 'অবজেক্ট' (অর্থ কী / মান জোড়ের সংগ্রহ), 'সংখ্যা', 'স্ট্রিং', বা 'অ্যারে'। এটাই. সংখ্যার, স্ট্রিং বা অ্যারে নয় এমন যে কোনও কিছুই, কনস্ট্রাক্টর (ক্রস উইন্ডো-নিরাপদ) নির্বিশেষে কী / মান জোড়ার সেট হিসাবে তুলনা করা উচিত। বস্তুর তুলনা করার সময়, আক্ষরিক সংখ্যার মান এবং সংখ্যার উদাহরণগুলিকে সমান করুন, তবে সংখ্যার সাথে স্ট্রিংকে জোর করবেন না।
ট্রায়ঙ্কো

50

আপনি যদি কোনও JSON লাইব্রেরি ব্যবহার করছেন তবে আপনি প্রতিটি বিষয়টিকে JSON হিসাবে এনকোড করতে পারেন, তারপরে সাম্যতার জন্য ফলাফলের স্ট্রিংগুলি তুলনা করুন।

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

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

দ্রষ্টব্য: যদিও এই উত্তরটি বেশিরভাগ ক্ষেত্রে কার্যকর হবে, কারণ বিভিন্ন ব্যক্তি বিভিন্ন কারণে মন্তব্যগুলিতে উল্লেখ করেছেন যে এটি বিভিন্ন কারণে সমস্যাযুক্ত। প্রায় সব ক্ষেত্রেই আপনি আরও শক্তিশালী সমাধান খুঁজতে চাইবেন।


91
আকর্ষণীয়, তবে আমার মতে কিছুটা জটিল। উদাহরণস্বরূপ, আপনি কি 100% গ্যারান্টি দিতে পারবেন যে বস্তুর বৈশিষ্ট্যগুলি সর্বদা একই ক্রমে উত্পন্ন হবে?
Guido

25
এটি একটি ভাল প্রশ্ন, এবং অন্যটিকে উত্থাপিত করে, যাতে বিভিন্ন অর্ডারে একই বৈশিষ্ট্যযুক্ত দুটি বস্তু সত্যই সমান কিনা। সমান দ্বারা আপনি কী বোঝাতে চান তার উপর নির্ভর করে, আমার ধারণা।
জোয়েল আনায়ের

11
নোট করুন যে বেশিরভাগ এনকোডার এবং স্ট্রিংফায়ার ফাংশন উপেক্ষা করে এবং এনএফ-এর মতো নন-চিরকালীন সংখ্যাগুলি বাতিল করে দেয়।
স্টিফেন বেলঞ্জার

4
আমি গাইডোর সাথে একমত, সম্পত্তি ক্রম গুরুত্বপূর্ণ এবং এটির নিশ্চয়তা দেওয়া যায় না। @ জোয়েলএনায়ার, আমি মনে করি বৈশিষ্ট্যের মান সমান হলে বিভিন্ন অর্ডারে একই বৈশিষ্ট্যযুক্ত দুটি বস্তুকে সমান বিবেচনা করা উচিত।
জুজার আলী

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]))
jib

2
আপনি যখন দুটি তারিখের তুলনা করছেন তখন এটি ব্যর্থ হয়
গ্রেগ

3
ডিপএকুয়াল ({}, []) সত্য ফিরে আসে
অ্যালেক্সমারলি-ফিঞ্চ

3
হ্যাঁ, আপনি যদি এই ধরণের কোণার ক্ষেত্রে : (x === y): (x === y && (x != null && y != null || x.constructor === y.constructor))
যত্নশীল হন তবে কুরুচিপূর্ণ সমাধানটি

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()ফাংশনই যাওয়ার উপায় হতে পারে।


এটি একটি দীর্ঘ পদ্ধতি তবে এটি প্রতিটি বস্তুর বৈশিষ্ট্যের ক্রমানুসারে কোনও অনুমান না করে অবজেক্টগুলিকে সম্পূর্ণরূপে পরীক্ষা করে।
biancollins081

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
আমি মনে করি না যে ব্রাউজার / ইঞ্জিনগুলিতে অর্ডার সংরক্ষণের নিশ্চয়তা রয়েছে।
জো লিস

@ জো লিস উদ্ধৃতি আবশ্যক;) আমি একাধিক ব্রাউজারে এটি পরীক্ষা করে পুনরায় স্মরণ করছি, ধারাবাহিক ফলাফল পেয়েছি। তবে অবশ্যই, ভবিষ্যতের ব্রাউজার / ইঞ্জিনগুলিতে কেউ একই আচরণের গ্যারান্টি দিতে পারে না। এটি সেরা হিসাবে একটি কৌশল (যেমন ইতিমধ্যে উত্তরে ডাকা হয়েছে) এবং আমি এটিকে বস্তুর তুলনা করার একটি নিশ্চিত উপায় হিসাবে বোঝাতে চাইনি।
এটেস গোলাল

1
অবশ্যই, এখানে কিছু পয়েন্টার রয়েছে: ইসিএমএসক্রিপ্ট স্পেস বলে যে অবজেক্টটি "অর্ডারড" নয় ; এবং বর্তমান ব্রাউজারগুলিতে প্রকৃত ডাইভারিং আচরণের জন্য এই উত্তর
জো লিস

2
@ জো লিস তার জন্য ধন্যবাদ! তবে দয়া করে নোট করুন আমি কখনই কোড এবং সংকলিত বস্তুর মধ্যে অর্ডার সংরক্ষণের দাবি করিনি was আমি এমন সম্পত্তিগুলির ক্রম সংরক্ষণের দাবি করছিলাম যার মানগুলি স্থানে প্রতিস্থাপিত হয়। এটাই ছিল আমার সমাধানের মূল চাবিকাঠি: কেবলমাত্র সম্পত্তি মানগুলি ওভাররাইট করতে একটি মিশ্রিন ব্যবহার করা use ধরে নেওয়া হচ্ছে বাস্তবায়নগুলি সাধারণত কিছু ধরণের হ্যাশম্যাপ ব্যবহার করতে পছন্দ করে, কেবল মানগুলির পরিবর্তে কীগুলির ক্রম সংরক্ষণ করা উচিত। বাস্তবে ঠিক এটিই আমি বিভিন্ন ব্রাউজারে পরীক্ষা করেছিলাম।
এটস গোলাল

1
@ অ্যাটসগোরাল: এই বাঁধাটিকে আরও কিছুটা স্পষ্ট করে তোলা সম্ভব (বোল্ডফেস, ...)। বেশিরভাগ লোকেরা চারপাশে লেখাটি না পড়ে কেবল অনুলিপি-পেস্ট করে ...
উইলিম ভ্যান ওনসেম

21

নোড.জেজে, আপনি এর নেটিভ ব্যবহার করতে পারেন 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;
ফলুশো ওলাদিপো

নোড.জেএস এর কয়েকটি সংস্করণ সেট করা 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
এটি বিজ্ঞপ্তিযুক্ত রেফারেন্স সহ সামগ্রীর জন্য কাজ করে না
Nate-Bit Int

13

আমি comparableJSON তুলনীয় যে আমার বস্তুর অনুলিপি উত্পাদন করতে এই ফাংশনটি ব্যবহার করি :

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
ভাল ধারণা (আমার ক্ষেত্রে অবজেক্টগুলি কেবল কী / মান-
জোড়গুলির

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

আমি কারও সাথে এর অনুরূপ কিছু পোস্ট করেছে কিনা জানি না, তবে এখানে একটি ফাংশন যা আমি অবজেক্টের সমতা পরীক্ষা করার জন্য করেছি made

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 এর প্রতিটি প্রপসগুলি অতিক্রম করার আগে এই চেকটি যুক্ত করুন (অবজেক্ট.সেটঅনউনপ্রোপার্টিনেমস (ক)। দৈর্ঘ্য! == অবজেক্ট.সেটঅনপ্রন্টি নামস (খ)। দৈর্ঘ্য) মিথ্যা ফেরত
হিথ

1
এটা সুস্পষ্ট যে যথাযথ সাম্যতা পরীক্ষক অবশ্যই পুনরাবৃত্ত হওয়া উচিত। আমি মনে করি এরকম একটি পুনরাবৃত্ত উত্তরের সঠিক উত্তর হওয়া উচিত। গৃহীত উত্তরটি কোড দেয় না এবং এটি কোনও
উপকারে

9

আপনারা যারা নোডজেএস ব্যবহার করছেন তাদের জন্য 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


মনে হয় এর পারফরম্যান্সটি ভাল হবে। কোন চিন্তা করো না. এমনকি আমি জটিল পরিস্থিতিতেও এটি ব্যবহার করি। আমরা যখন এটি ব্যবহার করি তখন অবাস্তবটির সম্পত্তি অবজেক্ট বা অ্যারে বহন করে থাকে কিনা তা আমাদের চিন্তা করতে হবে না। জসন.আর স্ট্রিংফাই এটিকে যাইহোক স্ট্রিং করে তোলে এবং জাভাস্ক্রিপ্টে স্ট্রিংগুলির তুলনা করা খুব বড় বিষয় নয়
ট্রিকআরট্রিট

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}));


এটি একটি সম্পূর্ণ কার্যকরী উত্তর, ধন্যবাদ @ অ্যাড্রিয়ানো স্প্যাডনি। আপনি কী জানেন যে কী কী / বৈশিষ্ট্যটি সংশোধন করা হয়েছিল আমি কীভাবে পেতে পারি? ধন্যবাদ,
ডিজিটালই

1
হাই @ ডিজিটাল, যদি আপনার প্রয়োজন হয় কোন কীগুলি আলাদা, তবে এটি আদর্শ ফাংশন নয়। অন্য উত্তরটি পরীক্ষা করুন এবং অবজেক্টগুলির মাধ্যমে একটি লুপ সহ একটি ব্যবহার করুন।
অ্যাড্রিয়ানো স্পাদোনি

5

আপনি _.isEqual(obj1, obj2)আন্ডারস্কোর.জেএস লাইব্রেরি থেকে ব্যবহার করতে পারেন ।

এখানে একটি উদাহরণ:

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 ফাংশন একটি "replacer" ফাংশন ক্ষণস্থায়ী দ্বারা তুলনা ফিল্টার করতে পারেন হয় https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON / স্ট্রিংফাই # উদাহরণ_আর ব্যবহার_পরিবর্তনকারী_প্রেমিটার )। নিম্নলিখিতটি কেবল "ডের্প" নামযুক্ত সমস্ত বস্তুর কীগুলির তুলনা করবে:

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
ওহ, আমিও ভুলে গিয়েছিলাম, তবে প্রথম টেস্ট অবজেক্টের সমান হয়ে ও জামিনের প্রাথমিক পরীক্ষা করার মাধ্যমে এই فنکشنটি দ্রুত বাড়ানো যেতে পারে যদি তারা একই বস্তু হয়: যদি (আপত্তি 1 === আপজ 2) সত্য ফিরে আসে;
th317

11
areEqual({a: 'b'}, {b: 'a'})পায় trueতাহলে?
Okm

হ্যাঁ, আমি পোস্ট করার পরে বুঝতে পারি যে এই "সমাধান" এর মধ্যে সমস্যা রয়েছে। বাছাইকরণ অ্যালগরিদমের আসলে সঠিকভাবে কাজ করতে এর জন্য আরও কিছুটা কাজের প্রয়োজন।
th317erd

4

কিছু এস features টি বৈশিষ্ট্য ব্যবহার করে বস্তুর তুলনায় আমার সংস্করণটি অবদান রাখতে চেয়েছিলেন। এটি কোনও অর্ডার আমলে নেয় না। সমস্ত কিছু যদি / অন্যথায় টার্নারি রূপান্তর করার পরে আমি নিম্নলিখিতটি নিয়ে এসেছি:

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
আমি এর বিভিন্নতা ব্যবহার করে শেষ করেছি। সদস্য সংখ্যা গণনা করার জন্য ধন্যবাদ!
NateS

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:{...}}বস্তুর মতো ফিরে আসবে।


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

আমি স্প্যাগেটি কোডের উত্তরগুলি দেখছি। কোনও তৃতীয় পক্ষের libs ব্যবহার না করে, এটি খুব সহজ।

প্রথমে দুটি জিনিসকে তাদের মূল নামগুলি দ্বারা বাছাই করুন।

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

আমি হ্যাশিং বা সিরিয়ালাইজেশনের বিরুদ্ধে পরামর্শ দেব (জেএসওএন সমাধানের পরামর্শ অনুসারে)। যদি দুটি পরীক্ষাগুলি সমান হয় তবে আপনাকে যদি পরীক্ষা করতে হয় তবে আপনাকে সমান অর্থ কী তা নির্ধারণ করতে হবে। এটি উভয় অবজেক্টের সমস্ত ডেটা সদস্য মিলে যায় বা এটি হতে পারে যে মেমরির অবস্থানগুলি অবশ্যই মেলাতে পারে (যার অর্থ উভয় ভেরিয়েবল মেমরিতে একই বস্তুর রেফারেন্স করে), বা প্রতিটি বস্তুর মধ্যে কেবলমাত্র একজন ডেটা সদস্যের মিল থাকতে পারে।

সম্প্রতি আমি একটি অবজেক্ট তৈরি করেছি যার কনস্ট্রাক্টর প্রতিটি বার একটি উদাহরণ তৈরি করার সময় একটি নতুন আইডি তৈরি করে (1 থেকে শুরু করে 1 দ্বারা বৃদ্ধি)। এই অবজেক্টটির একটি ইস্কুয়াল ফাংশন রয়েছে যা সেই আইডি মানকে অন্য কোনও অবজেক্টের আইডি মানের সাথে তুলনা করে এবং মিললে সত্য হয় true

সেক্ষেত্রে আমি "সমান" হিসাবে আইডি মানগুলির মিলের অর্থ হিসাবে সংজ্ঞা দিয়েছি। দেওয়া হয়েছে যে প্রতিটি উদাহরণের একটি অনন্য আইডি রয়েছে যা এই ধারণাটি কার্যকর করতে ব্যবহৃত হতে পারে যে মিলে যাওয়া অবজেক্টগুলি একই মেমরির অবস্থানও দখল করে। যদিও এটি প্রয়োজনীয় নয়।


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. আপনার ব্রাউজারে অবজেক্ট.কিসের জন্য সমর্থন রয়েছে

এটি একটি সাধারণ কৌশল হিসাবে প্রদর্শিত হিসাবে বিবেচনা করা উচিত।

/**
 * 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

এটি উপরের সমস্তটির জন্য একটি সংযোজন, কোনও প্রতিস্থাপন নয়। অতিরিক্ত পুনরাবৃত্তির কেসগুলি পরীক্ষা করার প্রয়োজন ছাড়াই আপনাকে অগভীর তুলনায় অবজেক্টগুলি তুলনা করতে হবে। এখানে একটি শট আছে।

এটি এর সাথে তুলনা করে: ১) নিজস্ব বৈশিষ্ট্যের সংখ্যার সমতা, ২) মূল নামের সমতা, ৩) বিসিপ্যাভারভ্যালু == সত্য হলে, সম্পত্তির সাথে সম্পর্কিত মানের মূল্য এবং তাদের ধরণের সমতা (ট্রিপল সমতা)

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লুপই যথেষ্ট।

জটিলতা হল ও (এন * এন) এর সাথে এনগুলির কীগুলির সংখ্যা।

আমি আশা করি / অনুমান করা বিষয়গুলি যেগুলি আমি সংজ্ঞায়িত করেছি তাতে 1000 টিরও বেশি সম্পত্তি থাকবে না ...


2

আমি জানি এটি কিছুটা পুরানো, তবে আমি এই সমস্যার জন্য আমি একটি সমাধান যুক্ত করতে চাই। আমার একটি অবজেক্ট ছিল এবং আমি জানতে চেয়েছিলাম এর ডেটা কখন পরিবর্তন হয়েছে। "অবজেক্ট.ওবিজারের অনুরূপ কিছু" এবং আমি যা করেছি তা হ'ল:

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]
jib
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.