जावास्क्रिप्ट में सरणियों की तुलना कैसे करें?


988

मैं दो सरणियों की तुलना करना चाहता हूं ... आदर्श रूप से, कुशलता से। कुछ भी नहीं फैंसी, बस trueअगर वे समान हैं, और falseयदि नहीं। आश्चर्य की बात नहीं है, तुलना ऑपरेटर काम नहीं करता है।

var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2);    // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2));    // Returns true

JSON प्रत्येक सरणी को एन्कोडिंग करता है, लेकिन क्या प्रत्येक मान के माध्यम से पुनरावृति के बिना केवल सरणियों की तुलना करने के लिए एक तेज़ या "बेहतर" तरीका है?


5
आप पहले उनकी लंबाई की तुलना कर सकते हैं, और यदि वे प्रत्येक मान के बराबर हैं।
TJHeuvel

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

48
@FelixKling, "समानता" को परिभाषित करना निश्चित रूप से एक सूक्ष्म विषय है, लेकिन उच्च स्तर की भाषाओं से जावास्क्रिप्ट पर आने वाले लोगों के लिए, उदासी का कोई बहाना नहीं है ([] == []) == false
एलेक्स डी

4
@ AlexD ऐसा लगता है कि सरणियाँ संदर्भ समानता का उपयोग करती हैं, जो आप उम्मीद करेंगे। यह बहुत भयानक होगा यदि आप ऐसा नहीं कर सकते हैं
जोनिआरा

3
@AlexD मैं कुछ ऐसी भाषा के बारे में नहीं सोच सकता जहाँ ऐसा नहीं होता है। C ++ में, आप दो बिंदुओं की तुलना करेंगे - असत्य। जावा में, आप जावास्क्रिप्ट के समान ही कर रहे हैं। PHP में, पर्दे के पीछे कुछ सरणियों के माध्यम से लूप होगा - क्या आप PHP को एक उच्च स्तरीय भाषा कहते हैं?
टॉम ज़ातो -

जवाबों:


877

सरणियों की तुलना करने के लिए, उनके माध्यम से लूप करें और हर मूल्य की तुलना करें:

तुलना सारणी:

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

उपयोग:

[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;

आप कह सकते हैं " लेकिन स्ट्रिंग्स की तुलना में यह बहुत तेज़ है - लूप नहीं ... " ठीक है, फिर आपको ध्यान देना चाहिए कि लूप हैं। पहला पुनरावर्ती लूप जो ऐरे को स्ट्रिंग में परिवर्तित करता है और दूसरा, जो दो तारों की तुलना करता है। तो यह विधि स्ट्रिंग के उपयोग से तेज है

मेरा मानना ​​है कि बड़ी मात्रा में डेटा को हमेशा सरणियों में संग्रहीत किया जाना चाहिए, न कि वस्तुओं में। हालाँकि यदि आप वस्तुओं का उपयोग करते हैं, तो उनकी तुलना आंशिक रूप से भी की जा सकती है।
ऐसे:

वस्तुओं की तुलना:

मैंने ऊपर कहा है, कि दो वस्तु उदाहरण कभी समान नहीं होंगे, भले ही वे इस समय समान डेटा हों:

({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666})  //false

इसका एक कारण है, उदाहरण के लिए, वस्तुओं के भीतर निजी चर हो सकते हैं।

हालाँकि, यदि आप डेटा रखने के लिए ऑब्जेक्ट संरचना का उपयोग करते हैं, तो तुलना करना अभी भी संभव है:

Object.prototype.equals = function(object2) {
    //For the first loop, we only check for types
    for (propName in this) {
        //Check for inherited methods and properties - like .equals itself
        //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
        //Return false if the return value is different
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        //Check instance type
        else if (typeof this[propName] != typeof object2[propName]) {
            //Different types => not equal
            return false;
        }
    }
    //Now a deeper check using other objects property names
    for(propName in object2) {
        //We must check instances anyway, there may be a property that only exists in object2
            //I wonder, if remembering the checked values from the first loop would be faster or not 
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        else if (typeof this[propName] != typeof object2[propName]) {
            return false;
        }
        //If the property is inherited, do not check any more (it must be equa if both objects inherit it)
        if(!this.hasOwnProperty(propName))
          continue;

        //Now the detail check and recursion

        //This returns the script back to the array comparing
        /**REQUIRES Array.equals**/
        if (this[propName] instanceof Array && object2[propName] instanceof Array) {
                   // recurse into the nested arrays
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
                   // recurse into another objects
                   //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        //Normal value comparison for strings and numbers
        else if(this[propName] != object2[propName]) {
           return false;
        }
    }
    //If everything passed, let's say YES
    return true;
}  

हालाँकि, याद रखें कि यह JSON की तुलना डेटा की तरह करना है, न कि क्लास इंस्टेंसेस और अन्य सामान की। यदि आप मोर जटिल वस्तुओं की तुलना करना चाहते हैं, तो इस उत्तर को देखें और यह सुपरलांग फ़ंक्शन है
इस कार्य को करने के लिए Array.equalsआपको मूल फ़ंक्शन को थोड़ा-थोड़ा संपादित करना होगा:

...
    // Check if we have nested arrays
    if (this[i] instanceof Array && array[i] instanceof Array) {
        // recurse into the nested arrays
        if (!this[i].equals(array[i]))
            return false;
    }
    /**REQUIRES OBJECT COMPARE**/
    else if (this[i] instanceof Object && array[i] instanceof Object) {
        // recurse into another objects
        //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
        if (!this[i].equals(array[i]))
            return false;
        }
    else if (this[i] != array[i]) {
...

मैंने दोनों कार्यों के लिए थोड़ा परीक्षण उपकरण बनाया ।

बोनस: के साथ नेस्टेड एरेज़ indexOfऔरcontains

सैमी बेनचरिफ़ ने उस मामले के लिए उपयोगी कार्य तैयार किए हैं जो आप नेस्टेड सरणियों में एक विशिष्ट वस्तु की खोज कर रहे हैं, जो यहां उपलब्ध हैं: https://jsfiddle.net/SamyBencherif/8352y6yw/


27
यदि आप this[i] !== array[i]इसके बजाय सख्त तुलनात्मक उपयोग करना चाहते हैं !=
टिम एस।

38
equalsइसके बजाय आपकी विधि को बुलाया जाना चाहिए compare। कम से कम .NET में, तुलना आमतौर पर एक हस्ताक्षर किए गए इंट को दर्शाता है कि कौन सी वस्तु अन्य की तुलना में अधिक है। देखें: तुलना
ओलिवर

15
Nt केवल इसे करने का सही तरीका है, यह काफी अधिक प्रभावशाली है। इस प्रश्न में सुझाई गई सभी विधियों के लिए मैंने एक त्वरित jsperf स्क्रिप्ट तैयार की है। jsperf.com/comparing-arrays2
टोलगा ई

96
बिल्ट-इन टाइप के प्रोटोटाइप को बदलना निश्चित रूप से सही तरीका नहीं है
जैस्पर

31
इसके अलावा, यह इस बारे में नहीं है कि क्या इसे फिर से लिखना आसान है, यह इस तथ्य के बारे में है कि एक उत्तर में कुछ ऐसा नहीं करना चाहिए जो बुरा अभ्यास माना जाता है ( developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/… ) और चाहिए निश्चित रूप से हेडर "सही तरीका" के नीचे ऐसा न करें
जैस्पर

386

जबकि यह केवल अदिश सरणियों के लिए काम करता है (नीचे नोट देखें), यह छोटा है:

array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})

Rr, ECMAScript 6 / कॉफी / टाइपस्क्रिप्ट में एरो फंक्शन्स के साथ:

array1.length === array2.length && array1.every((value, index) => value === array2[index])

(नोट: यहां 'स्केलर' का अर्थ उन मूल्यों से है जिनका उपयोग सीधे तुलना में किया जा सकता है ===। इसलिए: संदर्भों द्वारा संख्या, तार, ऑब्जेक्ट्स, संदर्भ द्वारा कार्य। तुलना ऑपरेटरों के बारे में अधिक जानकारी के लिए एमडीएन संदर्भ देखें ।)

अपडेट करें

मैंने टिप्पणियों से जो पढ़ा है, उससे सरणी को छांटना और तुलना करना सटीक परिणाम दे सकता है:

array1.length === array2.length && array1.sort().every(function(value, index) { return value === array2.sort()[index]});

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

array1 = [2,3,1,4];
array2 = [1,2,3,4];

फिर उपरोक्त कोड देना होगा true


19
मुझे यह पसंद है, हालांकि पाठकों को पता होना चाहिए कि यह केवल हल किए गए सरणियों पर काम करता है।
एलेन स्पार्टस

13
यह किसी भी प्रकार के सरणियों पर काम करता है, सॉर्ट किया गया या नहीं @espertus
मिशैल मिस्ज़ेसिस्ज़िन

36
हाँ बिल्कुल। इस फ़ंक्शन को दो सरणियों की तुलना करने के लिए माना जाता है, इससे कोई फर्क नहीं पड़ता कि वे सॉर्ट किए गए हैं या नहीं, उनके लगातार तत्वों को बराबर होना चाहिए।
मिशैल मिस्ज़ेसिस्ज़िन

22
@ एस्परटस वास्तव में, यह सच नहीं होगा यदि तत्वों में दोनों सरणियों में एक समान क्रम नहीं है। हालांकि, एक समानता जांच का लक्ष्य यह जांचना नहीं है कि क्या उनमें समान तत्व हैं, बल्कि यह जांचने के लिए कि क्या उनके पास समान आदेशों में समान तत्व हैं या नहीं।
क्वेंटिन रॉय

7
आप अगर दोनों सरणियों बराबरी, एक ही अवर्गीकृत आइटम वाले (लेकिन कई बार इस्तेमाल किया) कर रहे हैं जाँच करना चाहते हैं, तो आप उपयोग कर सकते हैं a1.length==a2.length && a1.every((v,i)=>a2.includes(v)): var a1 =[1,2,3], a2 = [3,2,1];( var a1 =[1,3,3], a2 = [1,1,3];काम की उम्मीद नहीं होगा के रूप में)
एमईएमएस

208

मैं सरणी / ऑब्जेक्ट भारी कोडिंग परियोजनाओं के लिए अंडरस्कोर लाइब्रेरी का उपयोग करना पसंद करता हूं ... अंडरस्कोर और लॉडश में चाहे आप सरणियों या वस्तुओं की तुलना कर रहे हों, यह सिर्फ इस तरह दिखता है:

_.isEqual(array1, array2)   // returns a boolean
_.isEqual(object1, object2) // returns a boolean

22
ध्यान दें कि आदेश मायने रखता है _.isEqual([1,2,3], [2,1,3]) => false
विटाली एलेस्कैस

3
या यदि आप केवल isEqualकार्यक्षमता चाहते हैं , तो आप हमेशा लॉश का उपयोग कर सकते हैं। विचाराधीन मॉड्यूल
नरक

6
आप शायद _.difference () का उपयोग कर सकते हैं; अगर आदेश आपके लिए कोई मायने नहीं रखता है
रॉनन क्विलेवर

5
अगर ऑर्डर में कोई फर्क नहीं पड़ता है तो हम इस चेक से पहले सरणी को सॉर्ट कर सकते हैं_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
फ़िल्टर '

सबसे संक्षिप्त और सीधा जवाब IMHO :-)
कीरान रयान

121

मुझे लगता है कि यह JSON स्ट्रिंग का उपयोग करने का सबसे सरल तरीका है, और यह कुछ स्थितियों में सबसे अच्छा समाधान हो सकता है:

JSON.stringify(a1) === JSON.stringify(a2);

यह वस्तुओं को a1और a2तारों में परिवर्तित करता है ताकि उनकी तुलना की जा सके। आदेश अधिकांश मामलों में महत्वपूर्ण है, इसके लिए उपरोक्त उत्तर में से एक में दिखाए गए सॉर्ट एल्गोरिथ्म का उपयोग करके ऑब्जेक्ट को सॉर्ट किया जा सकता है।

कृपया ध्यान दें कि आप ऑब्जेक्ट की तुलना नहीं कर रहे हैं, लेकिन ऑब्जेक्ट का स्ट्रिंग प्रतिनिधित्व। यह बिल्कुल वैसा नहीं हो सकता जैसा आप चाहते हैं।


अच्छा जवाब लेकिन क्यों [] == [] झूठे लौटे? दोनों साधारण वस्तु हैं फिर क्यों?
परदीप जैन

4
@PardeepJain, यह इसलिए है क्योंकि डिफ़ॉल्ट रूप से, ऑब्जेक्ट के लिए ECMAScript में समानता ऑपरेटर उसी मेमोरी लोकेशन का संदर्भ देते समय सही होता है। Var x = y = [] आज़माएँ; // अब समानता सच है।
राडटेक

7
सिर्फ यह ध्यान रखें कि JSON कड़ा हो जाना फ़ंक्शन त्वरित नहीं है। बड़े सरणियों के साथ उपयोग निश्चित रूप से अंतराल का परिचय देगा।
लुकास एलिसिस

6
यह प्रश्न विशेष रूप से पूछता है कि क्या JSON.stringify की तुलना में बेहतर / तेज तरीका है।
डॉन हैच

यह कुछ और स्थितियों के लिए एक अच्छा समाधान क्यों हो सकता है, इस पर अधिक विस्तार से मिलता है।
राडटेक 21

61

यह स्पष्ट नहीं है कि आप "समान" से क्या मतलब है। उदाहरण के लिए, सरणियाँ aऔर bनीचे समान हैं (नेस्टेड सरणियों पर ध्यान दें)?

var a = ["foo", ["bar"]], b = ["foo", ["bar"]];

यहाँ एक अनुकूलित सरणी तुलनात्मक फ़ंक्शन है जो सख्त समानता का उपयोग करके प्रत्येक सरणी के संबंधित तत्वों की तुलना करता है और सरणी तत्वों की पुनरावर्ती तुलना नहीं करता है जो स्वयं सरणियां हैं, जिसका अर्थ है कि उपरोक्त उदाहरण के लिए, arraysIdentical(a, b)वापस आ जाएगा false। यह सामान्य स्थिति में काम करता है, जो JSON- और join()आधारित समाधान नहीं करेगा:

function arraysIdentical(a, b) {
    var i = a.length;
    if (i != b.length) return false;
    while (i--) {
        if (a[i] !== b[i]) return false;
    }
    return true;
};

@ASDF: यह स्पष्ट नहीं है कि "समान" का क्या अर्थ है। जाहिर है कि यह जवाब सिर्फ उथली जाँच है। मैं एक नोट जोड़ूंगा।
टिम डाउन

यह arraysIdentical ([1, 2, [3, 2]], [1, 2, [3, 2]]) के लिए विफल रहता है;
गोपीनाथ शिव

4
@ गोपीनाथ शिव: ठीक है, यह केवल तभी विफल होता है जब आप इसे वापस करने की उम्मीद कर रहे हों true। उत्तर बताता है कि यह नहीं होगा। यदि आपको नेस्टेड सरणियों की तुलना करने की आवश्यकता है, तो आप आसानी से एक पुनरावर्ती चेक जोड़ सकते हैं।
टिम डाउन

59

व्यावहारिक तरीका है

मुझे लगता है कि यह कहना गलत है कि एक विशेष कार्यान्वयन "सही तरीका ™" है यदि यह "गलत" समाधान के विपरीत केवल "सही" ("सही") है। टॉम का समाधान स्ट्रिंग-आधारित सरणी तुलना पर एक स्पष्ट सुधार है, लेकिन इसका मतलब यह नहीं है कि इसका उद्देश्य "सही" है। वैसे भी सही क्या है ? क्या यह सबसे तेज है? क्या यह सबसे अधिक लचीला है? क्या इसे समझना सबसे आसान है? क्या यह डिबग करने के लिए सबसे तेज है? क्या यह कम से कम संचालन का उपयोग करता है? क्या इसका कोई साइड इफेक्ट है? किसी भी समाधान से सभी चीजों का सर्वश्रेष्ठ नहीं हो सकता है।

Tomáš कह सकता है कि उसका समाधान तेज़ है लेकिन मैं यह भी कहूंगा कि यह अनावश्यक रूप से जटिल है। यह एक ऑल-इन-वन समाधान बनने की कोशिश करता है जो सभी एरेज़, नेस्टेड या नहीं के लिए काम करता है। वास्तव में, यह इनपुट के रूप में केवल सरणियों से अधिक स्वीकार करता है और फिर भी "वैध" उत्तर देने का प्रयास करता है।


जेनरिक पुन: प्रयोज्यता प्रदान करते हैं

मेरे जवाब से समस्या अलग तरीके से सामने आएगी। मैं एक सामान्य arrayCompareप्रक्रिया से शुरू करूंगा जो केवल सरणियों के माध्यम से कदम रखने से संबंधित है। वहां से, हम अपने अन्य बुनियादी तुलना कार्यों जैसे arrayEqualऔर arrayDeepEqual, आदि का निर्माण करेंगे

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
  x === undefined && y === undefined
    ? true
    : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

मेरी राय में, सर्वोत्तम प्रकार के कोड को टिप्पणियों की भी आवश्यकता नहीं है, और यह कोई अपवाद नहीं है। यहां ऐसा बहुत कम हो रहा है कि आप इस प्रक्रिया के व्यवहार को लगभग बिना किसी प्रयास के समझ सकते हैं। निश्चित रूप से, ES6 के कुछ वाक्य-विन्यास आपको अभी विदेशी लग सकते हैं, लेकिन ऐसा केवल इसलिए है क्योंकि ES6 अपेक्षाकृत नया है।

जैसा कि प्रकार से पता चलता है, arrayCompareतुलना फ़ंक्शन fऔर दो इनपुट सरणियों को लेता है , xsऔर ys। अधिकांश भाग के लिए, हम जो भी करते हैं f (x) (y), वह इनपुट एरे में प्रत्येक तत्व के लिए होता है। falseयदि उपयोगकर्ता द्वारा परिभाषित fरिटर्न false- हम &&शॉर्ट-सर्किट मूल्यांकन के लिए धन्यवाद देते हैं , तो हम जल्दी लौटते हैं । तो हां, इसका मतलब है कि तुलनित्र जल्दी से चलना बंद कर सकता है और अनावश्यक होने पर बाकी इनपुट सरणी के माध्यम से लूपिंग को रोक सकता है।


सख्त तुलना

अगला, हमारे arrayCompareफ़ंक्शन का उपयोग करके , हम आसानी से अन्य कार्यों को बना सकते हैं जिनकी हमें आवश्यकता हो सकती है। हम प्राथमिक के साथ शुरू करेंगे arrayEqual...

// equal :: a -> a -> Bool
const equal = x => y =>
  x === y // notice: triple equal

// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
  arrayCompare (equal)

const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys))      //=> true
// (1 === 1) && (2 === 2) && (3 === 3)  //=> true

const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs))      //=> false
// (1 === '1')                          //=> false

इतना ही आसान। arrayEqualके साथ परिभाषित किया जा सकता है arrayCompareऔर एक तुलनित्र फ़ंक्शन aका bउपयोग करने के लिए तुलना करता है ===(सख्त समानता के लिए)।

ध्यान दें कि हम equalइसे स्वयं के कार्य के रूप में भी परिभाषित करते हैं। यह arrayCompareदूसरे डेटा प्रकार (एरे) के संदर्भ में हमारे पहले ऑर्डर तुलनित्र का उपयोग करने के लिए एक उच्च-क्रम फ़ंक्शन के रूप में भूमिका पर प्रकाश डालता है ।


तुलना की ढीली

हम इसके बजाय आसानी से परिभाषित arrayLooseEqualकर सकते हैं ==। अब 1(संख्या) की तुलना ( '1'स्ट्रिंग) करने पर, परिणाम होगा true...

// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
  x == y // notice: double equal

// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
  arrayCompare (looseEqual)

const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys))    //=> true
// (1 == '1') && (2 == '2') && (3 == '3')  //=> true

गहरी तुलना (पुनरावर्ती)

आपने शायद गौर किया है कि यह केवल उथले तुलना थो है। निश्चित रूप से टॉम का समाधान "द राइट वे ™" है, क्योंकि इसमें निहित तुलना गहरी है, है ना?

अच्छी तरह से हमारी arrayCompareप्रक्रिया एक तरह से उपयोग करने के लिए पर्याप्त है जो एक गहरी समानता का परीक्षण एक हवा बनाता है ...

// isArray :: a -> Bool
const isArray =
  Array.isArray

// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
  arrayCompare (a => b =>
    isArray (a) && isArray (b)
      ? arrayDeepCompare (f) (a) (b)
      : f (a) (b))

const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3')         //=> false

console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3')                 //=> true

इतना ही आसान। हम एक अन्य उच्च-क्रम फ़ंक्शन का उपयोग करके एक गहरे तुलनित्र का निर्माण करते हैं। इस बार हम arrayCompareएक कस्टम तुलनित्र का उपयोग कर रैपिंग कर रहे हैं जो यह जाँच करेगा कि क्या हैं aऔर bएरेज़ हैं। यदि हां, तो arrayDeepCompareफिर से अन्यथा तुलना करें aऔर bउपयोगकर्ता द्वारा निर्दिष्ट तुलनित्र ( f) के लिए। यह हमें गहरे तुलना व्यवहार को अलग रखने की अनुमति देता है कि हम वास्तव में व्यक्तिगत तत्वों की तुलना कैसे करते हैं। यानी, शो ऊपर के उदाहरण की तरह, हम गहरा का उपयोग कर की तुलना कर सकते equal, looseEqualया किसी भी अन्य तुलनित्र हम बनाते हैं।

क्योंकि arrayDeepCompareकरी है, हम इसे आंशिक रूप से लागू कर सकते हैं जैसे हमने पिछले उदाहरणों में भी किया था

// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
  arrayDeepCompare (equal)

// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
  arrayDeepCompare (looseEqual)

मेरे लिए, यह पहले से ही टॉम के समाधान पर एक स्पष्ट सुधार है क्योंकि मैं स्पष्ट रूप से अपने सरणियों के लिए उथले या गहरी तुलना का चयन कर सकता हूं, आवश्यकतानुसार।


वस्तु तुलना (उदाहरण)

अब अगर आपके पास वस्तुओं या कुछ और की एक सरणी है तो क्या होगा? हो सकता है कि आप उन सरणियों को "बराबर" मानना ​​चाहें, यदि प्रत्येक वस्तु का समान idमूल्य हो ...

// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
  x.id !== undefined && x.id === y.id

// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
  arrayCompare (idEqual)

const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2)            //=> true

const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6)            //=> false

इतना ही आसान। यहां मैंने वेनिला जेएस वस्तुओं का उपयोग किया है, लेकिन इस प्रकार का तुलनित्र किसी भी वस्तु प्रकार के लिए काम कर सकता है ; यहां तक ​​कि अपने कस्टम वस्तुओं। इस तरह के समानता परीक्षण का समर्थन करने के लिए टॉम के समाधान को पूरी तरह से फिर से तैयार करने की आवश्यकता होगी

वस्तुओं के साथ गहरी सरणी? एक समस्या नहीं है। हमने अत्यधिक बहुमुखी, सामान्य कार्य बनाए हैं, इसलिए वे विभिन्न प्रकार के उपयोग मामलों में काम करेंगे।

const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys))     //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

तुलनात्मक तुलना (उदाहरण)

या क्या होगा यदि आप किसी अन्य प्रकार की पूरी तरह से मनमानी तुलना करना चाहते थे? शायद मैं जानना चाहता हूं कि क्या प्रत्येक एक xसे अधिक है y...

// gt :: Number -> Number -> Bool
const gt = x => y =>
  x > y

// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)

const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys))     //=> true
// (5 > 2) && (10 > 4) && (20 > 8)  //=> true

const zs = [6,12,24]
console.log (arrayGt (xs) (zs))     //=> false
// (5 > 6)                          //=> false

थोड़ा ही काफी है

आप देख सकते हैं कि हम वास्तव में कम कोड के साथ अधिक कर रहे हैं। हमारे बारे में कुछ भी जटिल नहीं है arrayCompareऔर हमने जो भी कस्टम कम्पैक्टर बनाए हैं उनमें से प्रत्येक का बहुत ही सरल कार्यान्वयन है।

आसानी के साथ, हम परिभाषित कर सकते हैं वास्तव में दो सरणियों तुलना करने के लिए के लिए हम कैसे इच्छा - उथले, गहरी, सख्त, ढीले, किसी वस्तु संपत्ति, या कुछ मनमाने ढंग से गणना, या इनमें से किसी भी संयोजन - सब एक प्रक्रिया का उपयोग कर , arrayCompare। शायद एक RegExpतुलनित्र भी सपना ! मुझे पता है कि बच्चे उन रेगीक्स से कैसे प्यार करते हैं ...

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

क्या यह आपके लिए "सही" समाधान बनाता है? यह तय करने के लिए आप पर निर्भर है। और कोई भी आपके लिए ऐसा नहीं कर सकता है; केवल आप ही जानते हैं कि आपकी जरूरतें क्या हैं। लगभग सभी मामलों में, मैं चालाक और तेज तरह से सीधे, व्यावहारिक और बहुमुखी कोड को महत्व देता हूं। आपके लिए अलग मूल्य हो सकते हैं, इसलिए आपके लिए क्या काम करता है।


संपादित करें

मेरा पुराना उत्तर arrayEqualछोटे प्रक्रियाओं में विघटित होने पर अधिक केंद्रित था । यह एक दिलचस्प अभ्यास है, लेकिन वास्तव में इस समस्या से निपटने का सबसे अच्छा (सबसे व्यावहारिक) तरीका नहीं है। यदि आप रुचि रखते हैं, तो आप इस संशोधन इतिहास को देख सकते हैं।


8
"सबसे अच्छे प्रकार के कोड को भी टिप्पणियों की आवश्यकता नहीं होती है" ... इसे कहने के लिए नफरत है, लेकिन यह कोड टिप्पणी का अधिक उपयोग कर सकता है, और / या एक अलग नाम-- "तुलना" बहुत अस्पष्ट है। अगर मैं सही ढंग से पढ़ रहा हूँ, तो आपकी "तुलना" अनिवार्य रूप से एक पुनरावर्ती "हर" है। मुझे लगता है। या यह एक पुनरावर्ती "कुछ" है? हम्म। इसके लिए आवश्यकता से अधिक सोच की आवश्यकता है। शायद "बराबरी का रिश्ता" की मानक शब्दावली का लाभ उठाते हुए एक बेहतर नाम "एरेक्वेवलेंट" होगा। या, यहां तक ​​कि स्पष्ट (मुझे वैसे भी), "पुनरावर्ती रूप से"।
डॉन हैच

1
@ जवाब देने के अवसर के लिए धन्यवाद। "तुलना" से क्या आपका मतलब है arrayCompare? हां फ़ंक्शन करी है, लेकिन यह someऔर से अलग है every। तुलना करने के लिए arrayCompareएक तुलनित्र और दो सरणियाँ लेता है । मैंने विशेष रूप से सामान्य नाम चुना क्योंकि हम किसी भी मनमाने फ़ंक्शन का उपयोग करके सरणियों की तुलना कर सकते हैं। फ़ंक्शन परिलक्षित होता है इसलिए इसे नए सरणी तुलना फ़ंक्शन (जैसे, arrayEqual) बनाने के लिए विशेष किया जा सकता है । क्या आप बेहतर नाम सुझा सकते हैं? आपको किन क्षेत्रों में अतिरिक्त टिप्पणियों या स्पष्टीकरण की आवश्यकता है? मुझे चर्चा करने में खुशी हो रही है ^ _ ^
धन्यवाद

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

1
@ आफ़्टर, लेखक: सुपर उपयोगी उत्तर, अच्छा काम, +1। प्रतिक्रिया: आप सादगी की वकालत करते हैं, फिर भी कोई रास्ता नहीं है एक लाइन पर तीन तीरों के साथ एक अभिव्यक्ति सरल या कई डेवलपर्स के लिए समझने में आसान है। उदा: f => ([x, ... xs]) => ([y, ... ys]) =>। मैं लगातार इसका उपयोग करता हूं और अभी भी इसे "केवल इसे देखो" के बजाय मानसिक रूप से विघटित करना पड़ा। दूसरा बिंदु ftor सही है, हर का उपयोग करें। यहां तक ​​कि अपने कारणों को तौलना, संतुलन पर यह न केवल मुझे बेहतर लगता है, बल्कि आपके दृष्टिकोण से भी जब आपके डिजाइन दर्शन का अनुमान लगाने का प्रयास किया जाता है।
व्हाइटनीलैंड

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

54

मूल प्रश्न की भावना में:

मैं दो सरणियों की तुलना करना चाहता हूं ... आदर्श रूप से, कुशलतापूर्वककुछ भी नहीं फैंसी , बस सच है अगर वे समान हैं, और यदि नहीं तो गलत है।

मैं निम्नलिखित परिणामों के साथ यहां प्रस्तावित कुछ और सरल सुझावों पर प्रदर्शन परीक्षण चला रहा हूं (धीमी गति से)

जबकि (67%) टिम नीचे से

var i = a1.length;
while (i--) {
    if (a1[i] !== a2[i]) return false;
}
return true

user2782196 द्वारा हर (69%)

a1.every((v,i)=> v === a2[i]);

डीईआई द्वारा कम (74%)

a1.reduce((a, b) => a && a2.includes(b), true);

में शामिल होने और toString (78%) Gaizka Allende और विवेक से

a1.join('') === a2.join('');

a1.toString() === a2.toString();

विक्टर पालमो द्वारा आधा हिस्सा (90%)

a1 == a2.toString();

stringify (100%) radtek द्वारा

JSON.stringify(a1) === JSON.stringify(a2);

नीचे दिए गए उदाहरणों पर ध्यान दें कि एरे को क्रमबद्ध किया गया है, एकल-आयामी एरे। .lengthतुलना को एक सामान्य बेंचमार्क के लिए हटा दिया गया है ( a1.length === a2.lengthसुझावों में से किसी में जोड़ें और आपको ~ 10% प्रदर्शन को बढ़ावा मिलेगा)। प्रत्येक की गति और सीमा को जानने के लिए जो भी समाधान आपके लिए सबसे अच्छा है उसे चुनें।

असंबंधित नोट: यह देखने के लिए दिलचस्प है कि लोगों को इस सवाल के पूरी तरह से वैध जवाब पर डाउन वोट बटन पर सभी खुश-खुश जॉन वेन्स मिल रहे हैं।


लिंक एक खाली परीक्षण खोलता है।
अलेक्जेंडर अबाकुमोव

यदि आप सरणी आकार से टकराते हैं, तो ये संख्याएँ लागू नहीं होती हैं (विशेषकर अप्रोच कम)। साथ प्रयास करें Array.from({length: 1000}).map((a,v)=> $ {v}.padStart(10,2));
Narayon

यह केवल उथले सरणी के लिए काम करता है
रमेश राजेंद्रन

28

टोमैटो ज़ेटो के उत्तर को छोड़ते हुए, मैं मानता हूँ कि केवल सरणियों के माध्यम से पुनरावृति सबसे तेज़ है। अतिरिक्त रूप से (जैसा कि अन्य पहले ही बता चुके हैं), फ़ंक्शन को बराबर / बराबर कहा जाना चाहिए, तुलना नहीं। इसके प्रकाश में, मैंने समानता के लिए सरणियों की तुलना करने के लिए फ़ंक्शन को संशोधित किया - अर्थात उनके पास समान तत्व हैं, लेकिन ऑर्डर से बाहर - व्यक्तिगत उपयोग के लिए, और सोचा कि मैं इसे देखने के लिए सभी को यहां फेंक दूंगा।

Array.prototype.equals = function (array, strict) {
    if (!array)
        return false;

    if (arguments.length == 1)
        strict = true;

    if (this.length != array.length)
        return false;

    for (var i = 0; i < this.length; i++) {
        if (this[i] instanceof Array && array[i] instanceof Array) {
            if (!this[i].equals(array[i], strict))
                return false;
        }
        else if (strict && this[i] != array[i]) {
            return false;
        }
        else if (!strict) {
            return this.sort().equals(array.sort(), true);
        }
    }
    return true;
}

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

उदाहरण:

var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 4, 3];  // Loosely equal to 1
var arr3 = [2, 2, 3, 4];  // Not equal to 1
var arr4 = [1, 2, 3, 4];  // Strictly equal to 1

arr1.equals(arr2);         // false
arr1.equals(arr2, false);  // true
arr1.equals(arr3);         // false
arr1.equals(arr3, false);  // false
arr1.equals(arr4);         // true
arr1.equals(arr4, false);  // true

मैं भी समारोह और इस उदाहरण के साथ एक त्वरित jsfiddle ऊपर लिखा है:
http://jsfiddle.net/Roundaround/DLkxX/


12

भले ही इसके बहुत सारे उत्तर हों, लेकिन मेरा मानना ​​है कि मदद के लिए:

const newArray = [ ...new Set( [...arr1, ...arr2] ) ]

यह इस प्रश्न में नहीं कहा गया है कि सरणी की संरचना कैसी दिख रही है, इसलिए यदि आप यह सुनिश्चित करने के लिए जानते हैं कि आपके पास नेस्टेड सरणियाँ नहीं होंगी और न ही आप सरणी में ऑब्जेक्ट्स (यह मेरे साथ हुआ है, इसलिए मैं इस पर आया हूं उत्तर) उपरोक्त कोड काम करेगा।

क्या होता है कि हम दोनों सरणियों को समेटने के लिए स्प्रेड ऑपरेटर (...) का उपयोग करते हैं, फिर हम किसी डुप्लिकेट को समाप्त करने के लिए सेट का उपयोग करते हैं। एक बार आपके पास यह है कि आप उनके आकारों की तुलना कर सकते हैं, यदि तीनों सरणियों का आकार समान है, तो आप जाने के लिए अच्छे हैं।

यह उत्तर तत्वों के आदेश को भी नजरअंदाज करता है , जैसा कि मैंने कहा, सटीक स्थिति मेरे साथ हुई थी, इसलिए शायद उसी स्थिति में कोई व्यक्ति यहां समाप्त हो सकता है (जैसा मैंने किया)।


Edit1।

दिमित्री ग्रिन्को के प्रश्न का उत्तर देते हुए: "आपने यहां प्रसार ऑपरेटर (...) का उपयोग क्यों किया - नया सेट? यह काम नहीं करता है?"

इस कोड पर विचार करें:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

आपको मिलेगा

[ Set { 'a', 'b', 'c' } ]

उस मान के साथ काम करने के लिए आपको कुछ सेट संपत्तियों ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set देखें ) का उपयोग करने की आवश्यकता होगी । दूसरी ओर, जब आप इस कोड का उपयोग करते हैं:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ ...new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

आपको मिलेगा

[ 'a', 'b', 'c' ]

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


आपने यहाँ प्रसार ऑपरेटर (...) का उपयोग क्यों किया - नया सेट? यह काम नहीं करता है।
दिमित्री ग्रिन्को

दिमित्री ग्रिंको मुझे विश्वास है कि मैंने अपने Edit1 पर आपके प्रश्न का उत्तर दिया था। लेकिन मुझे यकीन नहीं है कि 'काम नहीं करता' कहकर आपका क्या मतलब है, क्योंकि दोनों जवाब आपको रास्ते में मिल सकते हैं
जेफरसन यूक्लिड्स

10

JSON.encode के समान तर्ज पर जॉइन () का उपयोग करना है।

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    //slice so we do not effect the original
    //sort makes sure they are in order
    //join makes it a string so we can do a string compare
    var cA = arrA.slice().sort().join(","); 
    var cB = arrB.slice().sort().join(",");

    return cA===cB;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];  //will return true

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //true

केवल समस्या यह है कि यदि आप उन प्रकारों की परवाह करते हैं जो अंतिम तुलना परीक्षण हैं। यदि आप प्रकारों के बारे में परवाह करते हैं, तो आपको लूप करना होगा।

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;

    //slice so we do not effect the orginal
    //sort makes sure they are in order
    var cA = arrA.slice().sort(); 
    var cB = arrB.slice().sort();

    for(var i=0;i<cA.length;i++){
         if(cA[i]!==cB[i]) return false;
    }

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false

यदि आदेश समान रहना चाहिए, तो यह केवल एक लूप है, किसी प्रकार की आवश्यकता नहीं है।

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    for(var i=0;i<arrA.length;i++){
         if(arrA[i]!==arrB[i]) return false;
    }

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,a) );  //true
console.log( checkArrays(a,b) );  //false
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false

3
यह केवल कुछ सरणियों के लिए काम करता है, और बड़े सरणियों के साथ बहुत धीमी गति से होगा।
टॉम ज़ातो - मोनिका

2
JSON उत्पन्न करना भी लूपिंग है, आप बस (या ऐसा लगता है) इसके बारे में नहीं जानते हैं। लूपिंग के अलावा, JSON उत्पन्न करने के लिए भी अधिक मेमोरी की आवश्यकता होती है - यह तुलना करने से पहले उक्त सरणियों के 2 स्ट्रिंग प्रतिनिधित्व बनाता है। डाउनवोट फ़ंक्शन को सर्वश्रेष्ठ से सबसे खराब से उत्तर देने के लिए कार्यान्वित किया जाता है। मुझे लगता है कि आपका उत्तर एक अच्छा उत्तर नहीं है, इसलिए मैंने इसे अस्वीकार कर दिया।
टॉम ज़ातो -

2
क्षमा करें, मैंने सिर्फ JSON के बजाय कहा .join()। हो सकता है कि अगर आपने अपने दूसरे समाधान को प्राथमिक कहा (जैसा कि यह बेहतर है, हालांकि बहुआयामी सरणियों के खिलाफ टूथलेस है), मैं आपको उस तरह से नहीं आंकूंगा। अब तक, मैंने उन सभी उत्तरों को नीचे कर दिया, जो एरेज़ को स्ट्रिंग्स में परिवर्तित करते हैं। साथ ही, मैंने उस सभी तरीके को सही तरीके से इस्तेमाल किया, जिस स्थिति में आपको पता होना चाहिए था। इसका मतलब है @Tim Down का जवाब और Bireys एक।
टॉम ज़ातो -

6
पहला संस्करण नाखून: checkArrays([1,2,3] , ["1,2",3]) == trueऔर यह बहुत संभावना नहीं है कि आप क्या करना चाहते हैं!
डॉक

2
@epascarello: हाँ, लेकिन आप (आपके द्वारा सुझाए गए बहुत लंबे विभाजक की अक्षमता से अलग) इसका अर्थ यह हो सकता है कि किनारे के मामले होंगे (जहां सरणी में आपके विभाजक के साथ एक स्ट्रिंग होती है) जहां चेकअरीज़ () फ़ंक्शन दुर्व्यवहार करता है । यह एक समस्या नहीं हो सकती है यदि आप सरणियों की सामग्री के बारे में कुछ जानते हैं (इसलिए आप एक विभाजक चुन सकते हैं जो आपको यकीन है कि सरणी आइटम में नहीं होगा), लेकिन अगर आप सामान्य सरणी-तुलना लिखने की कोशिश कर रहे हैं समारोह, तो join()इस तरह का उपयोग यह छोटी गाड़ी बनाता है!
चल रहा

7

यहाँ एक टाइपस्क्रिप्ट संस्करण है:

//https://stackoverflow.com/a/16436975/2589276
export function arraysEqual<T>(a: Array<T>, b: Array<T>): boolean {
    if (a === b) return true
    if (a == null || b == null) return false
    if (a.length != b.length) return false

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

//https://stackoverflow.com/a/16436975/2589276
export function arraysDeepEqual<T>(a: Array<T>, b: Array<T>): boolean {
    return JSON.stringify(a) === JSON.stringify(b)
}

मोचा के लिए कुछ परीक्षण मामले:

it('arraysEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']

    expect(arraysEqual(a, b)).to.equal(true)
    expect(arraysEqual(c, d)).to.equal(true)
    expect(arraysEqual(a, d)).to.equal(false)
    expect(arraysEqual(e, f)).to.equal(true)
    expect(arraysEqual(f, g)).to.equal(false)
})

it('arraysDeepEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']
    let h = [[1,2],'apple','banan8']
    let i = [[1,2],'apple','banan8']
    let j = [[1,3],'apple','banan8']

    expect(arraysDeepEqual(a, b)).to.equal(true)
    expect(arraysDeepEqual(c, d)).to.equal(true)
    expect(arraysDeepEqual(a, d)).to.equal(false)
    expect(arraysDeepEqual(e, f)).to.equal(true)
    expect(arraysDeepEqual(f, g)).to.equal(false)
    expect(arraysDeepEqual(h, i)).to.equal(true)
    expect(arraysDeepEqual(h, j)).to.equal(false)
})

6

यदि आप चाई अभिकथन पुस्तकालय के साथ मोचा जैसे परीक्षण ढांचे का उपयोग कर रहे हैं , तो आप सरणियों की तुलना करने के लिए गहरी समानता का उपयोग कर सकते हैं ।

expect(a1).to.deep.equal(a2)

यह तभी सही होना चाहिए जब सरणियों में संबंधित सूचकांकों पर समान तत्व हों।


6

यदि वे केवल संख्याओं या तारों के दो सरणियाँ हैं, तो यह एक त्वरित एक-पंक्ति है

const array1 = [1, 2, 3];
const array2 = [1, 3, 4];
console.log(array1.join(',') === array2.join(',')) //false

const array3 = [1, 2, 3];
const array4 = [1, 2, 3];
console.log(array3.join(',') === array4.join(',')) //true

const array1 = [1]; const array2 = [1, 1]; कंसोल.लॉग (array1.join ('') === array2.join ('')) // रिटर्न सच
डेन एम।

यह नहीं होना चाहिए: array1.join ('') '1' है और array2.join ('') '11' है
Gaizka Allende

क्षमा करें, टाइपो। पहला एरे होना चाहिए [11]। बहुत स्पष्ट है कि ऐसा क्यों होता है और कैसे ठीक करना है।
दान एम।

.Join () है "1" और [1,1] .join () "1,1" तो वे कभी नहीं के बराबर हो जाएगा है, [1]: सुनिश्चित नहीं हैं कि आप क्या कर रहे हैं के बारे में, यह बहुत आसान है
Gaizka Allende

कृपया, मेरी टिप्पणी को और अधिक ध्यान से पढ़ें। यदि आप अभी भी इसे नहीं देखते हैं, तो कृपया ideone.com/KFu427
Dan M.

5

मेरे मामले में तुलनात्मक सरणियों में केवल संख्याएँ और तार होते हैं। यह फ़ंक्शन आपको दिखाएगा कि यदि सरणियों में समान तत्व हैं।

function are_arrs_match(arr1, arr2){
    return arr1.sort().toString() === arr2.sort().toString()
}

चलिए इसे टेस्ट करते हैं!

arr1 = [1, 2, 3, 'nik']
arr2 = ['nik', 3, 1, 2]
arr3 = [1, 2, 5]

console.log (are_arrs_match(arr1, arr2)) //true
console.log (are_arrs_match(arr1, arr3)) //false

सवाल आपको सॉर्ट करने के लिए नहीं कहता है, इसलिए जैसे उदाहरण के लिए आपका समाधान गलत है are_arrs_equal([1,2], [2,1])। इसके अलावा, इस पृष्ठ पर अन्य चर्चाएँ देखें कि क्यों स्ट्रिंग अनावश्यक, नाजुक और गलत है।
अपने मॉड्स को अच्छी तरह

are_arrs_equal([1,2], [2,1])trueउम्मीद के मुताबिक वापसी हुई । शायद यह समाधान आदर्श नहीं है, लेकिन इसने मेरे लिए काम किया।
हांनिक

यह वास्तव में समस्या है, उन दोनों एक आदेश डेटा संरचना के लिए शब्द "बराबर" के किसी भी समझदारी में समान नहीं हैं । वे सरणियाँ हैं, सेट नहीं हैं, और यदि आप सेट समानता चाहते हैं तो आपको इसे कॉल करना चाहिए - और एक अलग प्रश्न का उत्तर देना चाहिए। :-)
अपने मॉड का अच्छी तरह से इलाज करें

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

1
के लिए विफल रहता है are_arrs_match([1,2], ["1,2"])(रिटर्न true)। और ध्यान दें कि the sort()कॉल इनपुट सरणियों को संशोधित करेगा - यह वांछनीय नहीं हो सकता है।
-कैच-अंततः

5

यह 2 अनरीड एरेज़ की तुलना करता है:

function areEqual(a, b) {
  if ( a.length != b.length) {
    return false;
  }
  return a.filter(function(i) {
    return !b.includes(i);
  }).length === 0;  
}

हालांकि महंगा (गणना संसाधनों के संदर्भ में), यह एक मजबूत समाधान है जो विभिन्न प्रकारों के लिए अच्छा होना चाहिए, और छंटाई पर भरोसा नहीं करता है!
user3.1415927

4

हम every( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every ) का उपयोग करके इसे कार्यात्मक तरीके से कर सकते हैं

function compareArrays(array1, array2) {
    if (array1.length === array2.length)
        return array1.every((a, index) => a === array2[index])
    else
        return false
}

// test
var a1 = [1,2,3];
var a2 = [1,2,3];

var a3 = ['a', 'r', 'r', 'a', 'y', '1']
var a4 = ['a', 'r', 'r', 'a', 'y', '2']

console.log(compareArrays(a1,a2)) // true
console.log(compareArrays(a1,a3)) // false
console.log(compareArrays(a3,a4)) // false

4

आपका कोड उचित रूप से मामले को तब नहीं संभालेगा जब दोनों सरणियों में समान तत्व हों लेकिन समान क्रम में नहीं।

अपने उदाहरण के साथ मेरे कोड पर एक नज़र डालें जो दो सरणियों की तुलना करता है जिनके तत्व संख्या हैं, आप इसे संशोधित कर सकते हैं या अन्य तत्व प्रकारों के लिए इसका विस्तार कर सकते हैं (.join () के बजाय .toString () का उपयोग करके)।

var a1 = [1,2,3];
var a2 = [1,2,3];
const arraysAreEqual = a1.sort().toString()==a2.sort().toString();
// true if both arrays have same elements else false
console.log(arraysAreEqual);


4

संख्या के एक सरणी के लिए प्रयास करें:

a1==''+a2

नोट: यह विधि तब काम नहीं करेगी जब सरणी में तार भी हों, जैसे a2 = [1, "2,3"]


3

Herer's my solution:

/**
 * Tests two data structures for equality
 * @param {object} x
 * @param {object} y
 * @returns {boolean}
 */
var equal = function(x, y) {
    if (typeof x !== typeof y) return false;
    if (x instanceof Array && y instanceof Array && x.length !== y.length) return false;
    if (typeof x === 'object') {
        for (var p in x) if (x.hasOwnProperty(p)) {
            if (typeof x[p] === 'function' && typeof y[p] === 'function') continue;
            if (x[p] instanceof Array && y[p] instanceof Array && x[p].length !== y[p].length) return false;
            if (typeof x[p] !== typeof y[p]) return false;
            if (typeof x[p] === 'object' && typeof y[p] === 'object') { if (!equal(x[p], y[p])) return false; } else
            if (x[p] !== y[p]) return false;
        }
    } else return x === y;
    return true;
};

किसी भी नेस्टेड डेटा संरचना के साथ काम करता है, और स्पष्ट रूप से वस्तुओं के तरीकों की अनदेखी करता है। इस विधि के साथ Object.prototype को विस्तारित करने के बारे में भी मत सोचो, जब मैंने एक बार यह कोशिश की थी, jQuery टूट गया;)

अधिकांश सरणियों के लिए यह अभी भी क्रमबद्ध समाधान के अधिकांश से तेज है। ऑब्जेक्ट रिकॉर्ड के सरणियों के लिए यह संभवतः सबसे तेज़ तुलना विधि है।


अच्छा नहीं! ये सच देते हैं: equal({}, {a:1})और equal({}, null)यह त्रुटियां निकलती हैं:equal({a:2}, null)
kristianlm

3
JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null

मैंने इस तरह से इसे किया।


अच्छा समाधान - लेकिन मुझे आश्चर्य है कि कुछ स्थितियों में अगर यह हमेशा की तरह काम नहीं करेगा, जैसे कि कुछ आदिम या गहरी नेस्टेड सरणियों के साथ? मुझे उम्मीद है कि यह सभी परिस्थितियों में काम करेगा
बेन रॉन्डेउ

3

2 सरणियों की तुलना:

var arr1 = [1,2,3];
var arr2 = [1,2,3];

function compare(arr1,arr2)
{
  if((arr1 == arr2) && (arr1.length == arr2.length))
    return true;
  else
    return false;
}

कॉलिंग फ़ंक्शन

var isBool = compare(arr1.sort().join(),arr2.sort().join());

यह उत्तर काम नहीं करेगा, जैसा कि === सरणियों के लिए अपेक्षित व्यवहार नहीं करता है।
माइकल यांग

जवाब काम करता है, हालांकि === का यहां कोई महत्व नहीं है (क्योंकि क्रमबद्ध () केवल सरणी पर काम करता है)। यहां तक ​​कि == भी काम करेगा।
अमय कुलकर्णी

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

यह सच है, हमने इसका इस्तेमाल किया है, लेकिन मैंने '===' को हटा दिया है क्योंकि यह अबाध नहीं है
अमय कुलकर्णी

आह, मैंने नोटिस नहीं किया कि आप एक स्ट्रिंग में कनवर्ट कर रहे थे और सॉर्ट करने और जुड़ने के बाद फ़ंक्शन को कॉल कर रहे थे; मेरी क्षमा याचनाएं।
माइकल यांग

3

मैं सादे JSऔर साथ में विश्वास करता हूं ECMAScript 2015, जो समझने में मीठा और सरल है।

var is_arrays_compare_similar = function (array1, array2) {

    let flag = true;

    if (array1.length == array2.length) {

        // check first array1 object is available in array2 index
        array1.every( array_obj => {
            if (flag) {
                if (!array2.includes(array_obj)) {
                    flag = false;
                }
            }
        });

        // then vice versa check array2 object is available in array1 index
        array2.every( array_obj => {
            if (flag) {
                if (!array1.includes(array_obj)) {
                    flag = false;
                }
            }
        });

        return flag;
    } else {
        return false;
    }

}

आशा है कि यह किसी की मदद करेगा।


1
इसके विपरीत जांच की आवश्यकता क्यों है? हम जानते हैं कि सरणियाँ समान आकार की होती हैं, इसलिए यदि array1 में प्रत्येक आइटम array2 में भी पाया जाता है; फिर हमें यह क्यों जाँचना होगा कि array2 में प्रत्येक आइटम array1 में भी है?
जेफ्रीहॉशर

2

टोमाटो ज़ातो विचार का विस्तार। टॉमस के Array.prototyp.compare को Array.prototype.compareIdentical नामक इन्फैक्ट होना चाहिए।

यह गुजरता है:

[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 2]]) === false;
[1, "2,3"].compareIdentical ([1, 2, 3]) === false;
[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].compareIdentical ([1, 2, 1, 2]) === true;

लेकिन विफल रहता है:

[[1, 2, [3, 2]],1, 2, [3, 2]].compareIdentical([1, 2, [3, 2],[1, 2, [3, 2]]])

यहाँ बेहतर है (मेरी राय में) संस्करण:

Array.prototype.compare = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time
    if (this.length != array.length)
        return false;

    this.sort();
    array.sort();
    for (var i = 0; i < this.length; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].compare(array[i]))
                return false;
        }
        else if (this[i] != array[i]) {
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;
        }
    }
    return true;
}

http://jsfiddle.net/igos/bcfCY/


2
-1। यदि यह आपके द्वारा दिए गए उदाहरण पर 'विफल' हो जाता है, तो यह केवल 'विफल' की कुछ हद तक मनमानी परिभाषा के लिए मामला है। आप उन दो अलग-अलग सरणियों को समान मानने की उम्मीद क्यों करेंगे? आपने यह भी नहीं बताया कि आप किस समानता की अवधारणा को यहां लागू करने की कोशिश कर रहे हैं, या यह एक समझदार या मददगार क्यों है, लेकिन ऐसा लगता है कि आप चाहते हैं कि बहुआयामी सरणियों की तुलना की जाए जैसे कि वे एकल-आयामी तक ढह गई थीं लोगों को। यदि हां, तो आपने यह भी हासिल नहीं किया है: [१,२] .compare ([[१,२]]) आपके संस्करण के साथ गलत है, ठीक वैसे ही जैसे टॉमॉज़ के साथ है।
मार्क अमेरी

जो मैं अनुमान लगा सकता हूं, उसके आधार पर, वह कह रहा है कि [1, 2, 3, 4] और [1, 3, 2, 4] की तुलना बराबर की जानी चाहिए (ऑर्डर कोई फर्क नहीं पड़ता)।
गौतम बद्रीनाथन

2
var a1 = [1,2,3,6];
var a2 = [1,2,3,5];

function check(a, b) {
  return (a.length != b.length) ? false : 
  a.every(function(row, index) {
    return a[index] == b[index];
  });
}  

check(a1, a2);

////// या ///////

var a1 = [1,2,3,6];
var a2 = [1,2,3,6];

function check(a, b) {
  return (a.length != b.length) ? false : 
  !(a.some(function(row, index) {
    return a[index] != b[index];
  }));
}  

check(a1, a2)

आप कुछ कार्य भी कर सकते हैं जो पूरी तरह से पुनरावृत्त नहीं होंगे यदि हम आवश्यक शर्त को पूरा करते हैं, जैसे कि ऊपर
वसंत

2

बहुत कम कोड के साथ एक और दृष्टिकोण ( ऐरे कम और ऐरे का उपयोग करना शामिल है ):

arr1.length == arr2.length && arr1.reduce((a, b) => a && arr2.includes(b), true)

यदि आप भी आदेश की समानता की तुलना करना चाहते हैं:

arr1.length == arr2.length && arr1.reduce((a, b, i) => a && arr2[i], true)
  • lengthजांच सुनिश्चित करती है कि एक सरणी में तत्वों के सेट सिर्फ एक दूसरे के एक सबसेट नहीं है।

  • Reducer का उपयोग एक सरणी के माध्यम से चलने और प्रत्येक आइटम को अन्य सरणी में खोजने के लिए किया जाता है। यदि एक आइटम को कम फ़ंक्शन रिटर्न नहीं मिला है false

    1. पहले उदाहरण में यह परीक्षण किया जा रहा है कि एक तत्व शामिल है
    2. आदेश के लिए दूसरा उदाहरण भी देखें

1
क्या आप इस उत्तर को स्पष्ट करने के लिए अपने कोड को थोड़ा समझा सकते हैं?
टेड

1. सरणी की लंबाई की तुलना यह सुनिश्चित करने के लिए करें कि एक सरणी दूसरे का उपसमूह नहीं है
डील्स

2. एक सरणी के माध्यम से चलने के लिए और दूसरे सरणी में प्रत्येक आइटम की खोज करने के लिए reducer का उपयोग करें। यदि एक आइटम को कम फ़ंक्शन नहीं मिलता है, तो वह 'गलत' हो जाता है
डील्स

@DEls: उत्तर में अपनी व्याख्या संपादित की (थोड़ा प्रतिपादित और विस्तारित)। अब आप अपनी टिप्पणियों को हटा सकते हैं और पहली टिप्पणी को ध्वजांकित कर सकते हैं और यह अप्रचलित है।
-कैच-अंततः

2

एक सरल दृष्टिकोण:

function equals(a, b) {
    if ((a && !b) || (!a && b) || (!a && !b) || (a.length !== b.length)) {
        return false;
    }

    var isDifferent = a.some(function (element, index) { 
        return element !== b[index];
    });

    return !isDifferent;
}

2

पहले से ही कुछ बेहतरीन जवाब हैं। लेकिन मैं एक एथर आइडिया साझा करना चाहूंगा, जो सरणियों की तुलना करने में विश्वसनीय साबित हुई है। हम JSON.stringify () का उपयोग करके दो सरणी की तुलना कर सकते हैं । यह सरणी से एक स्ट्रिंग बना देगा और इस प्रकार समानता के लिए दो सरणी से दो प्राप्त स्ट्रिंग्स की तुलना करेगा

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:1},2]) //true

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},2]) //false

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:1},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //true

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[4]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[5]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //true

2

पुनरावर्ती और नेस्टेड सरणियों पर काम करता है :

function ArrEQ(a1,a2){
   return( 
        //:Are both elements arrays?
        Array.isArray(a1)&&Array.isArray(a2) 
        ?
        //:Yes: Test each entry for equality:
        a1.every((v,i)=>(ArrEQ(v,a2[i])))
        :
        //:No: Simple Comparison:
        (a1===a2)
   );;
};;

console.log( "Works With Nested Arrays:" );
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]],
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]]
));;     
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"DIFFERENT:APPLES" ]]],
    [1,2,3,[4,5,[6,"DIFFERENT:ORANGES"]]]
));;  

2

NESTED सरणियों के साथ MULTIPLE तर्क के साथ काम करता है :

//:Return true if all of the arrays equal.
//:Works with nested arrays.
function AllArrEQ(...arrays){
    for(var i = 0; i < (arrays.length-1); i++ ){
        var a1 = arrays[i+0];
        var a2 = arrays[i+1];
        var res =( 
            //:Are both elements arrays?
            Array.isArray(a1)&&Array.isArray(a2) 
            ?
            //:Yes: Compare Each Sub-Array:
            //:v==a1[i]
            a1.every((v,i)=>(AllArrEQ(v,a2[i])))
            :
            //:No: Simple Comparison:
            (a1===a2)
        );;
        if(!res){return false;}
    };;
    return( true );
};;

console.log( AllArrEQ( 
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
));; 

2
In a simple way uning stringify but at same time thinking in complex arrays:

**Simple arrays**:  
var a = [1,2,3,4];  
var b = [4,2,1,4];  
JSON.stringify(a.sort()) === JSON.stringify(b.sort()) // true  

**Complex arrays**:  
var a = [{id:5,name:'as'},{id:2,name:'bes'}];  
var b = [{id:2,name:'bes'},{id:5,name:'as'}];  
JSON.stringify(a.sort(function(a,b) {return a.id - b.id})) === JSON.stringify(b.sort(function(a,b) {return a.id - b.id})) // true  

**Or we can create a sort function**  

function sortX(a,b) {  
return a.id -b.id; //change for the necessary rules  
}  
JSON.stringify(a.sort(sortX)) === JSON.stringify(b.sort(sortX)) // true  
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.