จะเปรียบเทียบอาร์เรย์ใน JavaScript ได้อย่างไร


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 กำหนด "ความเสมอภาค" แน่นอนหัวข้อบอบบาง แต่สำหรับคนที่จะมาถึง JavaScript ([] == []) == falseจากภาษาระดับสูงมีข้อแก้ตัวสำหรับความโง่เขลาที่ไม่เหมือนใคร
Alex D

4
@AlexD ดูเหมือนว่าอาร์เรย์ใช้ความเท่าเทียมกันของการอ้างอิงซึ่งเป็นสิ่งที่คุณคาดหวัง มันช่างน่ากลัวถ้าคุณทำอย่างนั้นไม่ได้
JonnyRaa

3
@AlexD ฉันไม่สามารถนึกถึงภาษาที่ไม่เกิดขึ้นได้ ใน C ++ คุณจะเปรียบเทียบสองพอยน์เตอร์ - false ใน Java คุณทำเช่นเดียวกับในจาวาสคริปต์ ใน PHP บางสิ่งที่อยู่เบื้องหลังจะวนไปตามอาร์เรย์ - คุณเรียกภาษา PHP ว่าภาษาระดับสูงกว่าไหม
Tomáš Zato - Reinstate Monica

คำตอบ:


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;

คุณอาจพูดว่า " แต่มันเร็วกว่ามากในการเปรียบเทียบสตริง - ไม่มีลูป ... " ดีแล้วคุณควรทราบว่ามีลูป วนซ้ำ recursive แรกที่แปลง Array เป็นสายอักขระและวินาทีที่เปรียบเทียบสองสาย ดังนั้นวิธีการนี้จะเร็วกว่าการใช้งานของสตริง

ฉันเชื่อว่าข้อมูลจำนวนมากควรถูกเก็บไว้ในอาร์เรย์เสมอไม่ใช่ในวัตถุ อย่างไรก็ตามหากคุณใช้วัตถุก็สามารถนำไปเปรียบเทียบกับบางส่วนได้
นี่คือวิธี:

การเปรียบเทียบวัตถุ:

ฉันได้กล่าวไว้ข้างต้นแล้วว่าอินสแตนซ์ของวัตถุสองรายการจะไม่เท่ากันแม้ว่าจะมีข้อมูลเดียวกันในขณะนี้:

({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

Samy Bencherif ได้เตรียมฟังก์ชั่นที่มีประโยชน์สำหรับกรณีที่คุณกำลังค้นหาวัตถุเฉพาะในอาร์เรย์ที่ซ้อนกันซึ่งมีให้ที่นี่: https://jsfiddle.net/SamyBencherif/8352y6yw/


27
หากคุณต้องการที่จะทำเปรียบเทียบเข้มงวดใช้แทนthis[i] !== array[i] !=
Tim S.

38
วิธีการของคุณควรจะเรียกแทนequals compareอย่างน้อยใน. NET การเปรียบเทียบมักจะส่งกลับ int ที่ลงนามแล้วซึ่งระบุว่าวัตถุใดดีกว่าอีกอันหนึ่ง ดู: Comparer.Compare
Oliver

15
Nt เท่านั้นนี่คือวิธีที่ถูกต้องในการทำมันยังมีประสิทธิภาพมากขึ้น นี่คือสคริปต์ jsperf ฉบับย่อที่ฉันเตรียมไว้สำหรับวิธีการทั้งหมดที่แนะนำในคำถามนี้ jsperf.com/comparing-arrays2
Tolga E

96
การเปลี่ยนต้นแบบของชนิดในตัวนั้นไม่ใช่วิธีที่ถูกต้อง
Jasper

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 / CoffeeScript / TypeScript ที่มีฟังก์ชั่นลูกศร:

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

(หมายเหตุ: 'เซนต์คิตส์และเนวิส' ที่นี่หมายถึงค่าที่สามารถเปรียบเทียบได้โดยตรงโดยใช้===ดังนั้น: ตัวเลข, สตริง, วัตถุโดยการอ้างอิง, ฟังก์ชั่นโดยการอ้างอิงดูการอ้างอิง MDNสำหรับข้อมูลเพิ่มเติมเกี่ยวกับผู้ประกอบการเปรียบเทียบ)

UPDATE

จากสิ่งที่ฉันอ่านจากความคิดเห็นการเรียงลำดับอาร์เรย์และการเปรียบเทียบอาจให้ผลลัพธ์ที่ถูกต้อง:

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
ฉันชอบสิ่งนี้ถึงแม้ว่าผู้อ่านควรระวังว่านี่จะใช้งานได้กับอาร์เรย์ที่เรียงลำดับเท่านั้น
Ellen Spertus

13
มันใช้งานได้กับอาร์เรย์ทุกประเภทเรียงลำดับหรือไม่ @espertus
Michał Miszczyszyn

36
ใช่แล้ว ฟังก์ชั่นนี้ควรจะเปรียบเทียบสองอาร์เรย์มันไม่สำคัญว่าจะเรียงหรือไม่องค์ประกอบที่ต่อเนื่องของพวกเขาจะต้องเท่ากัน
Michał Miszczyszyn

22
@ espertus แน่นอนว่ามันจะไม่กลับมาจริงถ้าองค์ประกอบไม่มีลำดับเดียวกันที่แน่นอนในทั้งสองอาร์เรย์ อย่างไรก็ตามเป้าหมายของการตรวจสอบความเท่าเทียมกันนั้นไม่ได้เป็นการตรวจสอบว่าพวกเขามีองค์ประกอบเดียวกัน แต่เพื่อตรวจสอบว่าพวกเขามีองค์ประกอบเดียวกันในคำสั่งซื้อเดียวกัน
เควนตินรอย

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];จะไม่ทำงานตามที่คาดไว้)
mems

208

ฉันชอบที่จะใช้ไลบรารี Underscore สำหรับโครงการเข้ารหัสอาเรย์ / ออบเจ็กต์หนัก ... ใน Underscore และ Lodash ไม่ว่าคุณจะเปรียบเทียบอาร์เรย์หรือวัตถุมันมีลักษณะเช่นนี้:

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

22
โปรดทราบว่าลำดับนั้นสำคัญ _.isEqual([1,2,3], [2,1,3]) => false
Vitaliy Alekask

3
หรือหากคุณต้องการเพียงแค่การisEqualใช้งานคุณสามารถใช้โมดูล lodash.isequal ได้ตลอดเวลา
hellatan

6
คุณสามารถใช้ _.difference (); หากคำสั่งซื้อไม่สำคัญสำหรับคุณ
Ronan Quillevere

5
เราสามารถเรียงลำดับอาร์เรย์ก่อนการตรวจสอบนี้หากคำสั่งซื้อไม่สำคัญ_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
Filype

คำตอบที่กระชับและตรงไปตรงมามากที่สุด IMHO :-)
Kieran Ryan

121

ฉันคิดว่านี่เป็นวิธีที่ง่ายที่สุดในการใช้ JSON stringify และอาจเป็นทางออกที่ดีที่สุดในบางสถานการณ์:

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

สิ่งนี้จะแปลงวัตถุa1และa2เป็นสตริงเพื่อให้สามารถเปรียบเทียบได้ ลำดับนั้นมีความสำคัญในกรณีส่วนใหญ่เนื่องจากสามารถเรียงลำดับวัตถุโดยใช้อัลกอริทึมการเรียงลำดับที่แสดงในคำตอบข้างต้นอย่างใดอย่างหนึ่ง

โปรดทราบว่าคุณไม่ได้เปรียบเทียบวัตถุอีกต่อไป แต่เป็นตัวแทนสตริงของวัตถุ อาจไม่ใช่สิ่งที่คุณต้องการอย่างแน่นอน


คำตอบที่ดี แต่ทำไม [] == [] กลับเท็จ? ทั้งสองเป็นวัตถุธรรมดาแล้วทำไม
Pardeep Jain

4
@PardeepJain นี่เป็นเพราะโดยค่าเริ่มต้นตัวดำเนินการความเท่าเทียมกันใน ECMAScript สำหรับวัตถุจะส่งกลับค่าจริงเมื่อพวกเขาอ้างอิงตำแหน่งหน่วยความจำเดียวกัน ลองใช้ var x = y = []; // ตอนนี้ความเท่าเทียมกลับมาจริง
radtek

7
เพียงเพื่อทราบว่าฟังก์ชั่น JSON stringify ไม่รวดเร็ว ใช้กับอาร์เรย์ขนาดใหญ่จะทำให้เกิดความล่าช้าอย่างแน่นอน
Lukas Liesis

6
คำถามนี้ถามโดยเฉพาะว่ามีวิธีที่ดีกว่า / เร็วกว่าการใช้ JSON.stringify
Don Hatch

มันได้รับรายละเอียดเพิ่มเติมว่าทำไมนี่อาจเป็นทางออกที่ดีสำหรับบางสถานการณ์
radtek

61

ไม่มีความชัดเจนในสิ่งที่คุณหมายถึงโดย "เหมือนกัน" ตัวอย่างเช่นมีอาร์เรย์aและbด้านล่างเหมือนกัน (หมายเหตุอาร์เรย์ที่ซ้อนกัน) หรือไม่

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

นี่คือการเพิ่มประสิทธิภาพฟังก์ชั่นการเปรียบเทียบอาร์เรย์ที่เปรียบเทียบองค์ประกอบที่สอดคล้องกันของแต่ละอาร์เรย์ในการเปิดใช้ความเท่าเทียมกันอย่างเข้มงวดและไม่ได้ทำเปรียบเทียบ recursive ขององค์ประกอบมากมายที่ตัวเองอาร์เรย์ซึ่งหมายความว่าสำหรับตัวอย่างข้างต้นจะกลับมาarraysIdentical(a, b) falseมันทำงานได้ในกรณีทั่วไปซึ่งโซลูชัน JSON- และjoin()- based จะไม่:

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: มันไม่ชัดเจนจากคำถามที่ว่า "เหมือนกัน" หมายถึงอะไร เห็นได้ชัดว่าคำตอบนี้จะตรวจสอบเพียงตื้น ฉันจะเพิ่มบันทึกย่อ
Tim Down

สิ่งนี้ล้มเหลวสำหรับ arraysIdentical ([1, 2, [3, 2]], [1, 2, [3, 2]])
Gopinath Shiva

4
@GopinathShiva: trueดีก็ล้มเหลวถ้าคุณคาดหวังว่ามันจะกลับมา คำตอบอธิบายว่ามันจะไม่ หากคุณต้องการเปรียบเทียบอาร์เรย์ที่ซ้อนกันคุณสามารถเพิ่มการตรวจสอบแบบเรียกซ้ำได้อย่างง่ายดาย
Tim Down

59

วิธีการปฏิบัติ

ฉันคิดว่ามันผิดที่จะบอกว่าการใช้งานเฉพาะอย่างนั้นคือ "The Right Way ™" ถ้ามันเป็น "ถูกต้อง" ("ถูกต้อง") ตรงกันข้ามกับวิธีแก้ปัญหา "ผิด" โซลูชันของTomášเป็นการปรับปรุงที่ชัดเจนเกี่ยวกับการเปรียบเทียบอาเรย์แบบสตริง แต่ไม่ได้หมายความว่ามัน "ถูกต้อง" อย่างเป็นกลาง อะไรคือสิ่งที่ถูกต้องหรือไม่? มันเร็วที่สุด? มันยืดหยุ่นที่สุดหรือไม่? มันง่ายที่สุดที่จะเข้าใจหรือไม่? การดีบักเร็วที่สุดหรือไม่ มันใช้การดำเนินงานน้อยที่สุดหรือไม่? มันมีผลข้างเคียงหรือไม่? ไม่มีใครสามารถแก้ไขสิ่งที่ดีที่สุดในทุกสิ่ง

โทมัสบอกได้ว่าวิธีแก้ปัญหาของเขานั้นเร็ว แต่ฉันก็บอกว่ามันซับซ้อนโดยไม่จำเป็น มันพยายามที่จะเป็นโซลูชั่นแบบ all-in-one ที่ใช้งานได้กับอาร์เรย์ทั้งหมดซ้อนกันหรือไม่ ในความเป็นจริงมันยอมรับมากกว่าเพียงแค่อาร์เรย์เป็นอินพุตและยังคงพยายามที่จะให้คำตอบ "ถูกต้อง"


ยาสามัญสามารถใช้ซ้ำได้

คำตอบของฉันจะเข้าหาปัญหาแตกต่างกัน ฉันจะเริ่มต้นด้วย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เป็นฟังก์ชั่นที่มีลำดับสูงกว่าเพื่อใช้ตัวเปรียบเทียบลำดับแรกของเราในบริบทของชนิดข้อมูลอื่น (Array)


การเปรียบเทียบแบบหลวม

เราสามารถกำหนดได้อย่างง่ายดายเพียงแค่arrayLooseEqualใช้==แทน ตอนนี้เมื่อเปรียบเทียบ1(Number) กับ'1'(String) ผลลัพธ์จะเป็น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

การเปรียบเทียบแบบลึก (แบบเรียกซ้ำ)

คุณอาจสังเกตเห็นว่านี่เป็นเพียงการเปรียบเทียบที่ตื้นเท่านั้น วิธีแก้ปัญหาของTomášคือ "The Right Way ™" เพราะมันจะเป็นการเปรียบเทียบที่ลึกโดยนัยใช่ไหม?

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หรือเปรียบเทียบอื่น ๆ ที่เราทำ

เนื่องจากarrayDeepComparecurried เราสามารถนำบางส่วนมาใช้ได้เหมือนในตัวอย่างก่อนหน้านี้เช่นกัน

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

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

ให้ฉันนี้แล้วการปรับปรุงวิธีการแก้ปัญหาที่ชัดเจนกว่าTomášเพราะฉันสามารถอย่างชัดเจนเลือกตื้นหรือลึกสำหรับการเปรียบเทียบอาร์เรย์ของฉันเป็นสิ่งจำเป็น


การเปรียบเทียบวัตถุ (ตัวอย่าง)

ทีนี้ถ้าคุณมีชุดของวัตถุหรืออะไรซักอย่างล่ะ? บางทีคุณอาจต้องการพิจารณาอาร์เรย์เหล่านั้นเป็น "เท่ากัน" ถ้าแต่ละวัตถุมี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

เรียบง่ายเหมือนที่ ที่นี่ฉันใช้วัตถุวานิลลา JS แต่ตัวเปรียบเทียบประเภทนี้สามารถทำงานกับวัตถุชนิดใดก็ได้ แม้แต่วัตถุที่คุณกำหนดเอง วิธีแก้ปัญหาของTomášจะต้องทำใหม่ทั้งหมดเพื่อรองรับการทดสอบความเสมอภาคแบบนี้

อาร์เรย์ลึกกับวัตถุ ไม่ใช่ปัญหา. เราสร้างฟังก์ชั่นทั่วไปที่หลากหลายและหลากหลายเพื่อให้สามารถใช้งานได้ในหลากหลายกรณี

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เปรียบเทียบ! ฉันรู้ว่าเด็ก ๆ รัก regexps เหล่านั้นอย่างไร

มันเร็วที่สุด? Nope แต่มันอาจไม่จำเป็นต้องเป็นอย่างใดอย่างหนึ่ง ถ้าความเร็วที่ใช้ในการวัดคุณภาพของรหัสของเราตัวชี้วัดเท่านั้นจำนวนมากของรหัสที่ดีจริงๆจะได้โยนไป - นั่นคือเหตุผลที่ผมเรียกวิธีการนี้ในทางปฏิบัติทาง หรืออาจจะยุติธรรมมากกว่านี้เป็นวิธีปฏิบัติ คำอธิบายนี้เหมาะสำหรับคำตอบนี้เพราะฉันไม่ได้กำลังบอกว่าคำตอบนี้ใช้ได้เฉพาะเมื่อเปรียบเทียบกับคำตอบอื่น ๆ มันเป็นความจริงอย่างเป็นกลาง เราได้รับการปฏิบัติจริงในระดับสูงโดยมีรหัสน้อยมากซึ่งง่ายต่อการให้เหตุผล ไม่มีรหัสอื่นที่สามารถบอกได้ว่าเราไม่ได้รับคำอธิบายนี้

นั่นทำให้โซลูชัน "ถูกต้อง" สำหรับคุณหรือไม่? ขึ้นอยู่กับคุณที่จะตัดสินใจ และไม่มีใครสามารถทำเพื่อคุณได้ มีเพียงคุณเท่านั้นที่รู้ว่าความต้องการของคุณคืออะไร ในเกือบทุกกรณีฉันให้ความสำคัญกับรหัสตรงไปตรงมาการใช้งานและเอนกประสงค์มากกว่าความฉลาดและความรวดเร็ว สิ่งที่คุณให้คุณค่าอาจแตกต่างกันดังนั้นเลือกสิ่งที่เหมาะกับคุณ


แก้ไข

คำตอบเก่าของฉันมุ่งเน้นไปที่การย่อยสลายarrayEqualเป็นขั้นตอนเล็ก ๆ มันเป็นแบบฝึกหัดที่น่าสนใจ แต่ไม่ใช่วิธีที่ดีที่สุด (ในทางปฏิบัติมากที่สุด) ในการแก้ไขปัญหานี้ หากคุณสนใจคุณสามารถดูประวัติการแก้ไขนี้ได้


8
"โค้ดที่ดีที่สุดไม่ต้องการแม้แต่ความคิดเห็น" ... เกลียดที่จะพูด แต่โค้ดนี้สามารถใช้ความคิดเห็นได้มากกว่าและ / หรือชื่ออื่น - "การเปรียบเทียบ" นั้นค่อนข้างคลุมเครือ ถ้าฉันอ่านอย่างถูกต้อง "การเปรียบเทียบ" ของคุณนั้นเป็นคำที่ซ้ำซาก "ทุก ๆ " ฉันคิด. หรือว่า "บางคน" ซ้ำแล้วซ้ำอีก อืมมม สิ่งนี้ต้องการความคิดมากกว่าที่จำเป็น บางทีชื่อที่ดีกว่าน่าจะเป็น "arraysEquivalent" ซึ่งใช้ประโยชน์จากคำศัพท์มาตรฐานของ "ความสัมพันธ์ที่เท่าเทียมกัน" หรือชัดเจนยิ่งขึ้น (สำหรับฉันต่อไป) "เรียกซ้ำซ้ำซาก"
Don Hatch

1
@ DonHatch ขอบคุณสำหรับโอกาสที่จะตอบ โดย "เปรียบเทียบ" คุณหมายถึงarrayCompareอะไร ใช่ฟังก์ชั่นนี้เป็นแกงกะหรี่ แต่มันแตกต่างจากและsome ใช้ตัวเปรียบเทียบและสองอาร์เรย์เพื่อเปรียบเทียบ ฉันเลือกชื่อสามัญโดยเฉพาะเพราะเราสามารถเปรียบเทียบอาร์เรย์โดยใช้ฟังก์ชันใดก็ได้ ฟังก์ชั่นถูกปิดกั้นเพื่อให้สามารถสร้างฟังก์ชั่นการเปรียบเทียบอาเรย์ใหม่ได้ (เช่น, ) คุณช่วยแนะนำชื่อที่ดีกว่านี้ได้ไหม? คุณรู้สึกว่าพื้นที่ใดต้องการความคิดเห็นหรือคำอธิบายเพิ่มเติม? ฉันยินดีที่จะพูดคุย ^ _ ^everyarrayComparearrayEqual
ขอบคุณ

1
ไม่แน่ใจว่าถ้าจุดของฉันชัดเจน - แต่ประเด็นของฉันคือ, ฟังก์ชั่นของคุณไม่ได้ตั้งใจที่จะใช้ฟังก์ชั่นโดยพลการฉันไม่คิดว่า - มันตั้งใจที่จะใช้ ความสัมพันธ์ที่เท่าเทียมกัน นั่นเป็นสิ่งสำคัญ - มันจะไม่ทำสิ่งใดที่สมเหตุสมผล (ฉันไม่คิดว่า) หากได้รับฟังก์ชันเลขฐานสองแบบอื่นเช่นที่ฉันพูดถึงแม้แต่คนที่คนมักเรียกว่า "เปรียบเทียบ" ดังนั้นฉันคิดว่ามันจะมีประโยชน์ที่จะใส่ "เทียบเท่า" ในชื่อแทน "เปรียบเทียบ"
Don Hatch

1
@ftor ผู้แต่ง: คำตอบที่เป็นประโยชน์มากทำงานได้ดี +1 คำติชม: คุณสนับสนุนความเรียบง่าย แต่ก็ไม่มีวิธีใดที่แสดงออกด้วยลูกศรสามตัวในบรรทัดเดียวหรือเข้าใจง่ายสำหรับนักพัฒนาจำนวนมาก ตัวอย่างเช่น: f => ([x, ... xs]) => ([y, ... ys]) => ฉันใช้สิ่งนี้อย่างต่อเนื่องและยังต้องย่อยสลายทางจิตใจมากกว่า "เพียงแค่ดูมัน" ftor จุดที่สองนั้นถูกต้องใช้ทุกอย่าง แม้แต่การชั่งเหตุผลของคุณการทรงตัวไม่เพียง แต่ดีกว่าสำหรับฉัน แต่ยังมาจากมุมมองของคุณเมื่อพยายามสรุปปรัชญาการออกแบบของคุณ
whitneyland

1
ฉันเข้าใจว่านี่เป็นสถานที่สำหรับการเรียนรู้ แต่ฉันตั้งสมมติฐานที่นี่ว่าโปรแกรมเมอร์โดยเฉลี่ยที่เรียนรู้รูปแบบการทำงานสามารถเปลี่ยนฟังก์ชั่น curried ใด ๆ ให้เป็นแบบไม่มีการเปิด คำตอบของฉันไม่ได้ให้คำแนะนำว่าสไตล์นี้มีไว้เพื่อใช้ในโปรแกรมของคุณ - เขียนโดยไม่มีการเขียนเขียนโดยใช้กฎการเยื้องของคุณเขียนตามที่คุณต้องการ - ฉันเขียนคำตอบในสไตล์ที่ฉันเชื่อว่าเป็นการแสดงออก โปรแกรมที่ดีที่สุด ฉันยังต้องการที่จะเชิญคนอื่น ๆ ที่จะท้าทายวิธีที่เราแสดงโปรแกรมของเรา syntactically
ขอบคุณ

54

ด้วยจิตวิญญาณของคำถามเดิม:

ฉันต้องการที่จะเปรียบเทียบสองอาร์เรย์ ... นึกคิดได้อย่างมีประสิทธิภาพ ไม่มีอะไรแฟนซีแค่จริงถ้าพวกเขาเหมือนกันและเป็นเท็จถ้าไม่

ฉันใช้การทดสอบประสิทธิภาพกับคำแนะนำง่ายๆที่เสนอที่นี่พร้อมผลลัพธ์ต่อไปนี้(เร็วถึงช้า):

ในขณะที่ (67%)โดย Tim Down

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

ทุกคน (69%)โดยผู้ใช้ 2782196

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

ลดลง (74%)โดย DEIs

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

เข้าร่วม & toString (78%)โดย Gaizka Allende & vivek

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

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

ครึ่งถึงสายรัด (90%)โดย Victor Palomo

a1 == a2.toString();

stringify (100%)โดย radtek

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

โปรดสังเกตตัวอย่างด้านล่างสมมติว่ามีการเรียงลำดับอาร์เรย์อาร์เรย์แบบมิติเดียว .lengthการเปรียบเทียบถูกลบออกสำหรับการวัดประสิทธิภาพทั่วไป (เพิ่มa1.length === a2.lengthในคำแนะนำใด ๆ และคุณจะได้รับการเพิ่มประสิทธิภาพประมาณ 10%) เลือกวิธีแก้ไขปัญหาที่เหมาะสมที่สุดสำหรับคุณในการรู้ความเร็วและข้อ จำกัด ของแต่ละข้อ

หมายเหตุที่ไม่เกี่ยวข้อง:เป็นเรื่องที่น่าสนใจที่จะเห็นผู้คนได้รับ John Waynes ที่มีความสุขในการกดปุ่มลงคะแนนเสียงบนคำตอบที่ถูกต้องสมบูรณ์แบบสำหรับคำถามนี้


ลิงก์จะเปิดการทดสอบที่ว่างเปล่า
อเล็กซานเด Abakumov

หากคุณชนขนาดอาเรย์ตัวเลขเหล่านี้จะไม่ถูกนำไปใช้ (โดยเฉพาะวิธีลดขนาด) ลองด้วยArray.from({length: 1000}).map((a,v)=> $ {v}.padStart(10,2));
Narayon

ใช้งานได้กับอาเรย์ตื้นเท่านั้น
Ramesh Rajendran

28

เมื่อสร้างคำตอบของTomáš Zato ฉันยอมรับว่าการวนซ้ำในอาร์เรย์นั้นเร็วที่สุด นอกจากนี้ (เช่นเดียวกับคนอื่น ๆ ที่ระบุไว้แล้ว) ฟังก์ชันควรถูกเรียกว่าเท่ากับ / เท่ากันไม่ใช่การเปรียบเทียบ ในแง่นี้ฉันได้ปรับเปลี่ยนฟังก์ชั่นเพื่อจัดการการเปรียบเทียบอาร์เรย์สำหรับความคล้ายคลึงกัน - นั่นคือพวกมันมีองค์ประกอบเหมือนกัน แต่ไม่เป็นระเบียบ - สำหรับการใช้งานส่วนตัวและคิดว่าฉันจะเอามันใส่ที่นี่เพื่อให้ทุกคนได้เห็น

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

มันไม่ได้ระบุไว้ในคำถามว่าโครงสร้างของอาเรย์จะเป็นอย่างไรดังนั้นถ้าคุณรู้ว่าคุณจะไม่มีอาเรย์ซ้อนกันหรือวัตถุในอาเรย์ของคุณ (มันเกิดขึ้นกับฉันนั่นเป็นสาเหตุที่ฉันมาที่นี่ คำตอบ) โค้ดด้านบนจะใช้งานได้

สิ่งที่เกิดขึ้นคือเราใช้ตัวดำเนินการ spread (... ) เพื่อเชื่อมทั้งสองอาร์เรย์จากนั้นเราใช้ Set เพื่อกำจัดรายการที่ซ้ำกัน เมื่อคุณได้แล้วคุณสามารถเปรียบเทียบขนาดของพวกเขาถ้าทั้งสามอาร์เรย์มีขนาดเท่ากันคุณก็พร้อมที่จะไป

คำตอบนี้ยังไม่สนใจลำดับขององค์ประกอบอย่างที่ฉันพูดสถานการณ์ที่แน่นอนเกิดขึ้นกับฉันดังนั้นอาจมีบางคนในสถานการณ์เดียวกันอาจจบลงที่นี่ (เหมือนที่ฉันทำ)


Edit1

ตอบคำถามของ Dmitry Grinko: "ทำไมคุณถึงใช้ผู้ดำเนินงานสเปรด (... ) ที่นี่ - ... ชุดใหม่มันไม่ทำงาน"

พิจารณารหัสนี้:

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

คุณจะได้รับ

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

ในการทำงานกับค่าดังกล่าวคุณจะต้องใช้คุณสมบัติ Set (ดู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' ]

นั่นคือความแตกต่างอดีตจะให้เซตกับฉันมันก็ใช้ได้เหมือนกันกับที่ฉันจะได้ขนาดของเซตนั้น แต่อันหลังให้อาเรย์ที่ฉันต้องการซึ่งจะตรงกับความละเอียดมากขึ้น


ทำไมคุณถึงใช้ตัวดำเนินการสเปรด (... ) ที่นี่ - ... ชุดใหม่ มันไม่ทำงาน
Dmitry Grinko

Dmitry Grinko ฉันเชื่อว่าฉันตอบคำถามของคุณใน Edit1 ของฉัน แต่ฉันไม่แน่ใจว่าคุณหมายถึงอะไรโดยพูดว่า 'มันไม่ทำงาน' เพราะทั้งสองคำตอบสามารถทำให้คุณได้รับ
Jeferson Euclides

10

ในบรรทัดเดียวกันกับ JSON.encode คือการใช้ join ()

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
สิ่งนี้ใช้ได้กับอาร์เรย์บางตัวเท่านั้นและช้ามากกับอาร์เรย์ขนาดใหญ่
Tomáš Zato - Reinstate Monica

2
การสร้าง JSON กำลังวนลูปเหมือนกันคุณแค่ (หรือดูเหมือนว่า) ไม่รู้เกี่ยวกับมัน นอกเหนือจากการวนซ้ำการสร้าง JSON ยังต้องการหน่วยความจำเพิ่มเติม - มันสร้างการแทนค่าสตริง 2 ครั้งของอาร์เรย์ดังกล่าวก่อนที่จะเปรียบเทียบ มีการใช้งานฟังก์ชั่น downwote เพื่อเรียงลำดับคำตอบจากดีที่สุดถึงแย่ที่สุด ฉันคิดว่าคำตอบของคุณไม่ใช่คำตอบที่ดีดังนั้นฉันจึงลงคะแนน
Tomáš Zato - Reinstate Monica

2
ขออภัยผมแค่พูด JSON .join()แทน บางทีถ้าคุณระบุวิธีแก้ปัญหาที่สองของคุณเป็นหลัก (เพราะเป็นวิธีที่ดีกว่าแม้ว่าจะไม่มีฟันกับอาร์เรย์หลายมิติ) ฉันจะไม่ตัดสินคุณอย่างนั้น จนถึงตอนนี้ฉันได้ลดคำตอบทั้งหมดที่แปลงอาร์เรย์เป็นสตริง และฉันก็สนับสนุนทุกสิ่งที่ใช้อย่างถูกต้องในกรณีที่คุณจำเป็นต้องรู้ นี่หมายถึงคำตอบของ @Tim Down และหนึ่งใน Bireys
Tomáš Zato - Reinstate Monica

6
เวอร์ชันแรก FAILS: checkArrays([1,2,3] , ["1,2",3]) == trueและไม่น่าเป็นไปได้อย่างมากว่านั่นคือสิ่งที่คุณต้องการจะเกิดขึ้น!
Doin

2
@epascarello: ใช่คุณสามารถ แต่ (นอกเหนือจากความไม่มีประสิทธิภาพของตัวคั่นที่ยาวมากที่คุณแนะนำ) มันหมายความว่าจะมีกรณีขอบ (ที่อาร์เรย์เกิดขึ้นเพื่อให้มีสตริงที่มีตัวคั่นของคุณอยู่ในนั้น) ที่ checkArrays () ฟังก์ชั่น . นี่อาจไม่ใช่ปัญหาหากคุณรู้บางอย่างเกี่ยวกับเนื้อหาของอาร์เรย์ (เพื่อให้คุณสามารถเลือกตัวแยกที่คุณแน่ใจว่าจะไม่อยู่ในรายการอาร์เรย์) แต่ถ้าคุณกำลังพยายามเขียนการเปรียบเทียบอาร์เรย์ทั่วไปฟังก์ชั่นแล้วใช้join()เช่นนี้ทำให้รถอย่างละเอียด!
Doin

7

นี่คือรุ่นของ typescript:

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

หากคุณใช้กรอบการทดสอบเช่นMochaกับไลบรารีการยืนยันChaiคุณสามารถใช้ความเท่าเทียมกันอย่างลึกซึ้งในการเปรียบเทียบอาร์เรย์

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]; console.log (array1.join ('') === array2.join ('')) // คืนค่าจริง
Dan M.

ไม่ควร: array1.join ('') คือ '1' และ array2.join ('') คือ '11'
Gaizka Allende

ขอโทษพิมพ์ผิด [11]แถวแรกที่ควรจะ ค่อนข้างชัดเจนว่าทำไมสิ่งนี้ถึงเกิดขึ้นและวิธีแก้ไข
Dan M.

ไม่แน่ใจว่าคุณเป็นอะไรมันค่อนข้างง่าย: [1] .join () คือ "1" และ [1,1] .join () คือ "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])คำถามที่ไม่ได้ขอให้คุณจัดเรียงเพื่อแก้ปัญหาของคุณไม่ถูกต้องตัวอย่างเช่น ดูการสนทนาอื่น ๆ ในหน้านี้ด้วยว่าทำไมการสร้างสตริงจึงไม่จำเป็นบอบบางและผิด
ปฏิบัติต่อ mods ของคุณให้ดีใน

are_arrs_equal([1,2], [2,1])ผลตอบแทนtrueตามที่คาดไว้ บางทีวิธีนี้อาจไม่เหมาะ แต่ก็ใช้ได้กับฉัน
ใช่นิก

นั่นเป็นปัญหาที่แม่นยำทั้งสองนั้นไม่เท่ากันในความหมายใด ๆ ของคำว่า "เท่ากัน" สำหรับโครงสร้างข้อมูลที่ได้รับคำสั่ง พวกเขากำลังอาร์เรย์ไม่ได้ตั้งค่าและถ้าคุณต้องการตั้งค่าความเท่าเทียมกันคุณควรเรียกมันว่า - และจะตอบคำถามที่แตกต่างกัน :-)
ปฏิบัติต่อ mods ของคุณดี

1
ฉันเห็นด้วยกับความคิดเห็นข้างต้น แต่วิธีนี้ใช้ได้สำหรับฉันในอาร์เรย์จำนวนเต็มแบบเรียบง่ายซึ่งคำสั่งซื้อไม่สำคัญดังนั้นฉันจะใช้มัน
tomazahlin

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

5

สำหรับอาร์เรย์ของตัวเลขลอง:

a1==''+a2

หมายเหตุ:a2 = [1, "2,3"]วิธีการนี้จะไม่ทำงานเมื่ออาร์เรย์นอกจากนี้ยังมีสายเช่น


เคล็ดลับที่ฉลาด ..
javadba

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


3

นี่คือทางออกของฉัน:

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

นี่คือสิ่งที่ฉันทำ


วิธีแก้ปัญหาที่ดี - แต่ฉันสงสัยว่าในบางสถานการณ์ถ้ามันไม่ทำงานตามที่ตั้งใจไว้เสมอเช่นกับบางอย่างดั้งเดิมหรืออาร์เรย์ที่ซ้อนกันอย่างลึกล้ำ? ฉันหวังว่ามันจะใช้ได้ในทุกสถานการณ์แม้ว่า
Ben Rondeau

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

คำตอบนี้จะไม่ทำงานเนื่องจาก === ไม่ทำงานตามที่คาดไว้สำหรับอาร์เรย์
Michael Yang

คำตอบใช้ได้ผลแม้ว่า === จะไม่มีความสำคัญใด ๆ ที่นี่ (เนื่องจากการเรียงลำดับ () ทำงานในอาร์เรย์เท่านั้น) แม้แต่ == ก็สามารถใช้ได้เช่นกัน
Amay Kulkarni

ลองด้วยตัวคุณเอง มันพิมพ์เท็จถ้าคุณเรียกใช้รหัสนี้ นี่เป็นเพราะการเปรียบเทียบค่าอ้างอิงของอาร์เรย์โดยทั้ง == และ === แทนที่จะเป็นค่าจริง == และ === มีไว้สำหรับการเปรียบเทียบชนิดดั้งเดิมเท่านั้น
Michael Yang

มันกลับมาจริงเราได้ใช้มัน แต่ฉันได้ลบ '===' ตอนนี้เพราะมันไม่จำเป็น
Amay Kulkarni

อ่าฉันไม่ได้สังเกตว่าคุณกำลังแปลงเป็นสตริงและเรียกใช้ฟังก์ชันหลังจากเรียงลำดับและเข้าร่วม ฉันขอโทษ
Michael Yang

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 ด้วยหรือไม่
JeffryHouser

2

ขยายแนวคิดTomáš Zato Array.prototype.compare ของโทมัสควรเป็น infact ที่เรียกว่า 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 หากมัน 'ล้มเหลว' ในตัวอย่างที่คุณให้มานั่นเป็นเพียงกรณีของคำนิยามที่ค่อนข้าง 'ล้มเหลว' เท่านั้น ทำไมคุณถึงคิดว่าสองอาร์เรย์ที่ต่างกันจะได้รับการพิจารณาให้เท่าเทียมกัน? คุณยังไม่ได้อธิบายถึงแนวคิดของ 'ความเท่าเทียมกัน' ที่คุณพยายามนำมาใช้ที่นี่หรือทำไมมันเป็นเหตุผลที่สมเหตุสมผลหรือมีประโยชน์ แต่ดูเหมือนว่าคุณต้องการให้อาร์เรย์หลายมิติถูกเปรียบเทียบราวกับว่ามันถูกยุบลงเป็นมิติเดียว คน ถ้าเป็นเช่นนั้นคุณไม่ได้ทำเช่นนั้น: [1,2] .compare ([[1,2]]) ให้เท็จกับเวอร์ชั่นของคุณเหมือนกับของTomáš
Mark Amery

จากสิ่งที่ฉันสามารถอนุมานได้เขากำลังบอกว่าควรเปรียบเทียบ [1, 2, 3, 4] และ [1, 3, 2, 4] เท่ากัน (คำสั่งซื้อไม่สำคัญ)
Gautham Badhrinathan

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)

คุณสามารถฟังก์ชั่นบางอย่างได้เช่นกันซึ่งจะไม่วนซ้ำอย่างสมบูรณ์หากเราได้รับเงื่อนไขตามที่ต้องการเช่นด้านบน
Vasanth

2

วิธีการอื่นที่มีรหัสน้อยมาก (ใช้Array ลดและArray รวมถึง ):

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ตรวจสอบทำให้แน่ใจว่าชุดขององค์ประกอบในหนึ่งอาร์เรย์ไม่ได้เป็นเพียงส่วนย่อยของอีกองค์ประกอบหนึ่ง

  • ตัวลดจะใช้ในการเดินผ่านหนึ่งอาเรย์และค้นหาแต่ละรายการในอาเรย์อื่น falseหากหนึ่งในรายการไม่พบลดผลตอบแทนที่ฟังก์ชั่น

    1. ในตัวอย่างแรกมันถูกทดสอบว่าองค์ประกอบรวมอยู่
    2. ตัวอย่างที่สองตรวจสอบใบสั่งด้วย

1
คุณช่วยอธิบายรหัสเล็กน้อยเพื่อให้คำตอบชัดเจนขึ้นได้ไหม
ted

1. เปรียบเทียบความยาวของอาเรย์เพื่อให้แน่ใจว่าอาเรย์หนึ่งไม่ได้เป็นส่วนย่อยของอีกอัน
DEls

2. ใช้ตัวลดเพื่อเดินผ่านหนึ่งอาเรย์แล้วค้นหาแต่ละรายการในอาเรย์อื่น หากไม่พบหนึ่งรายการฟังก์ชันการลดจะส่งกลับ 'false'
DEls

@DEls: แก้ไขคำอธิบายของคุณเป็นคำตอบ (ป้อนข้อความใหม่และขยายเล็กน้อย) ตอนนี้คุณสามารถลบความคิดเห็นของคุณและตั้งค่าสถานะความคิดเห็นแรกและความคิดเห็นนี้ล้าสมัย
ลองจับ - ในที่สุด


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

เรียกซ้ำและทำงานในอาร์เรย์NESTED :

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 :

//: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  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.