Bagaimana mengetahui apakah dua larik memiliki nilai yang sama


105

Saya memiliki dua array ini: satu diisi dengan informasi dari permintaan ajax dan yang lainnya menyimpan tombol yang diklik pengguna. Saya menggunakan kode ini (saya isi dengan nomor sampel):

var array1 = [2, 4];
var array2 = [4, 2]; //It cames from the user button clicks, so it might be disordered.
array1.sort(); //Sorts both Ajax and user info.
array2.sort();
if (array1==array2) {
    doSomething();
}else{
    doAnotherThing();
}

Tapi itu selalu memberi false, meski dua larik itu sama, tapi dengan nama berbeda. (Saya memeriksa ini di Konsol JS Chrome). Jadi, adakah cara saya bisa mengetahui jika kedua array ini berisi sama? Mengapa memberi false? Bagaimana saya bisa tahu nilai mana di larik pertama yang tidak ada di larik kedua?


1
Saya cukup yakin Anda harus melalui setiap elemen array.
Thomas Li

Apakah Anda tahu mengapa hasilnya palsu? Ingin tahu.
RobW


kemungkinan duplikat dari cara memeriksa array javascript sama?
Palec

Jawaban:


36
function arraysEqual(_arr1, _arr2) {

    if (!Array.isArray(_arr1) || ! Array.isArray(_arr2) || _arr1.length !== _arr2.length)
      return false;

    var arr1 = _arr1.concat().sort();
    var arr2 = _arr2.concat().sort();

    for (var i = 0; i < arr1.length; i++) {

        if (arr1[i] !== arr2[i])
            return false;

    }

    return true;

}

Perhatikan bahwa ini tidak mengubah larik asli tidak seperti jawaban sebelumnya.


2
pengurutan membutuhkan waktu nlog (n). Anda tidak perlu menyortir. Jawaban stackoverflow.com/a/55614659/3209523 ini bekerja dalam waktu linier.
canbax

Menggunakan naskah ketikan Array.isArray () menyebabkan kesalahan, menghapus itu bekerja dengan baik.
Ariel Frischer

89

Jika item array Anda bukan objek- jika berupa angka atau string, misalnya, Anda dapat membandingkan string yang digabungkan untuk melihat apakah mereka memiliki anggota yang sama dalam urutan apa pun-

var array1= [10, 6, 19, 16, 14, 15, 2, 9, 5, 3, 4, 13, 8, 7, 1, 12, 18, 11, 20, 17];
var array2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];

if(array1.sort().join(',')=== array2.sort().join(',')){
    alert('same members');
}
else alert('not a match');

2
Ini akan bekerja dengan baik untuk primitif atau objek yang memiliki nilai toString yang mengidentifikasi secara unik, tetapi tidak untuk sembarang objek.
devios1

Terima kasih! solusi rapi
Gaston Sanchez

3
Waspadalah terhadap item nol dan penyortiran. Saya berakhir dengan string untuk membandingkan seperti ", 2,2,3" dan "2,2,3", yang tentu saja tidak sepenuhnya sama.
barbara.post

2
Bisa gagal untuk string, yaitu ['a', 'b']dan ['a,b']. Saya hanya akan merekomendasikan teknik ini untuk skrip kecil sekali pakai.
alex

1
@alex - dalam kasus saya, koma diperbolehkan dalam string tetapi titik koma tidak diperbolehkan, jadi saya menggunakan ';' untuk bergabung alih-alih koma
a2345sooted

45

Jika Anda ingin memeriksa hanya jika dua larik memiliki nilai yang sama (terlepas dari jumlah kemunculan dan urutan setiap nilai), Anda dapat melakukan ini dengan menggunakan lodash :

_.isEmpty(_.xor(array1, array2))

Pendek, sederhana dan cantik!


1
Saya tidak bisa menemukannya xordi dokumen garis bawah? Apakah Anda memikirkan IODash?
Patrick Mencias-lewis

44
Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { //To test values in nested arrays
            if (!this[i].compare(testArr[i])) return false;
        }
        else if (this[i] !== testArr[i]) return false;
    }
    return true;
}

var array1 = [2, 4];
var array2 = [4, 2];
if(array1.sort().compare(array2.sort())) {
    doSomething();
} else {
    doAnotherThing();
}

Mungkin?


Terima kasih! Ini bekerja seperti yang diinginkan. Saya memodifikasi sedikit fungsi sehingga saya juga bisa mengetahui berapa banyak ketidakcocokan.
Carlos Precioso

false untuk [2,4] [4,2].
Suraz Khanal

@SurazKhanal Masih perlu menyortir
Aaron McMillin

27

Mengapa kode Anda tidak berfungsi

JavaScript memiliki tipe data primitif dan tipe data non-primitif.

Untuk tipe data primitif, ==dan ===periksa apakah hal-hal di kedua sisi bilah memiliki nilai yang sama. Itulah mengapa 1 === 1benar.

Untuk tipe data non-primitif seperti array, ==dan ===periksa persamaan referensi. Artinya, mereka memeriksa apakah arr1dan arr2merupakan objek yang sama. Dalam contoh Anda, dua larik memiliki objek yang sama dalam urutan yang sama, tetapi tidak ekuivalen.

Solusi

Dua larik, arr1dan arr2, memiliki anggota yang sama jika dan hanya jika:

  • Semua yang ada di arr2dalamarr1

DAN

  • Semua yang ada di arr1dalamarr2

Jadi ini akan melakukan triknya (ES2016):

const containsAll = (arr1, arr2) => 
                arr2.every(arr2Item => arr1.includes(arr2Item))

const sameMembers = (arr1, arr2) => 
                        containsAll(arr1, arr2) && containsAll(arr2, arr1);

sameMembers(arr1, arr2); // `true`

Solusi kedua ini menggunakan Underscore lebih dekat dengan apa yang Anda coba lakukan:

arr1.sort();
arr2.sort();

_.isEqual(arr1, arr2); // `true`

Ini berfungsi karena isEqualmemeriksa "kesetaraan mendalam", yang berarti ia melihat lebih dari sekadar persamaan referensi dan membandingkan nilai.

Solusi untuk pertanyaan ketiga Anda

Anda juga bertanya bagaimana cara mengetahui hal-hal mana arr1yang tidak terkandung di dalamnyaarr2 .

Ini akan melakukannya (ES2015):

const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];

arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`

Anda juga bisa menggunakan differencemetode Underscore's :

_.difference(arr1, arr2); // `[4]`

MEMPERBARUI

Lihat komentar @ Redu — solusi saya adalah untuk sameMembers, tetapi yang ada dalam pikiran Anda mungkin sameMembersInOrderjuga dikenal sebagai deepEquals.

UPDATE 2

Jika Anda tidak peduli tentang urutan anggota array, ES2015 + Setmungkin merupakan struktur data yang lebih baik daripada Array. Lihat catatan MDN tentang cara menerapkan isSupersetdandifference menggunakan penambalan monyet yang berbahaya.


1
Solusi Anda salah. "Dua array, arr1 dan arr2, memiliki anggota yang sama jika dan hanya jika: Segala sesuatu di arr2 ada di arr1 DAN Segala sesuatu di arr1 ada di arr2" ini juga salah. Ini adalah array, bukan satu set. Jadi sameMembers([1,1,2],[2,1,2]);harus mengembalikan false.
Redu

1
@Redu menebak itu tergantung pada apa artinya "anggota yang sama" —saya mengartikannya "memiliki anggota yang sama". sameMembers([1,1,2],[2,1,2])harus kembali true, menurut saya. sameMembersInOrder([1,1,2],[2,1,2])AKA deepEquals([1,1,2],[2,1,2])harus kembali false.
Max Heiber

Solusi ketiga Anda arr1.filter...hanya akan bekerja untuk memeriksa apakah arr2 memiliki semua elemen arr1 atau tidak tetapi tidak sebaliknya yang juga diperlukan.
Aakash Verma

10

Pemeriksaan kesetaraan objek:JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

Tes di atas juga bekerja dengan array objek yang menggunakan fungsi sortir seperti yang didokumentasikan di http://www.w3schools.com/jsref/jsref_sort.asp

Mungkin cukup untuk array kecil dengan skema JSON datar.


9

Tujuan kami pada dasarnya adalah untuk memeriksa apakah 2 array adalah set yang sama. set adalah didefinisikan secara matematis set . Penyortiran tercepat secara asimtotik membutuhkan waktu O (nlog (n)) . Jadi jika Anda mengurutkan sebuah array, itu akan memakan waktu setidaknya O (nlog (n)) . Tetapi Anda dapat melakukan tugas ini lebih cepat , yang secara asimtotik memerlukan waktu O (n) (kasus rata-rata bukan kasus terburuk) dengan struktur data kamus. Di JS, kamus hanyalah sebuah objek dengan kunci dan nilai.

/** assumes array elements are primitive types
* check whether 2 arrays are equal sets.
* @param  {} a1 is an array
* @param  {} a2 is an array
*/
function areArraysEqualSets(a1, a2) {
  const superSet = {};
  for (const i of a1) {
    const e = i + typeof i;
    superSet[e] = 1;
  }

  for (const i of a2) {
    const e = i + typeof i;
    if (!superSet[e]) {
      return false;
    }
    superSet[e] = 2;
  }

  for (let e in superSet) {
    if (superSet[e] === 1) {
      return false;
    }
  }

  return true;
}

Perhatikan bahwa fungsi ini bekerja dengan array dari tipe dan asumsi primitif a1dan a2merupakan array.


5

Bagaimana dengan ini? ES 2017 saya kira:

const array1 = [1, 3, 5];
const array2 = [1, 5, 3];

const isEqual = (array1.length === array2.length) && (array1.every(val => array2.includes(val)));
console.log(isEqual);

Kondisi pertama memeriksa apakah kedua larik memiliki panjang yang sama dan kondisi kedua memeriksa apakah larik pertama adalah subset dari larik ke-2. Menggabungkan 2 kondisi ini kemudian harus menghasilkan perbandingan semua item dari 2 larik terlepas dari urutan elemennya.

Kode di atas hanya akan berfungsi jika kedua larik memiliki item non-duplikat.


3

Saat Anda membandingkan kedua larik tersebut, Anda membandingkan objek yang mewakili larik, bukan isinya.

Anda harus menggunakan fungsi untuk membandingkan keduanya. Anda dapat menulis sendiri yang hanya mengulang satu dan membandingkannya dengan yang lain setelah Anda memeriksa bahwa panjangnya sama.


3

Solusi sederhana untuk kesetaraan dangkal menggunakan ES6:

const arr1test = arr1.slice().sort()
const arr2test = arr2.slice().sort()
const equal = !arr1test.some((val, idx) => val !== arr2test[idx])

Membuat salinan dangkal dari setiap larik dan mengurutkannya. Kemudian gunakan some()untuk mengulang melalui arr1testnilai, memeriksa setiap nilai terhadap nilai arr2testdengan indeks yang sama. Jika semua nilai sama, some()mengembalikan false, dan pada gilirannya equalmengevaluasi ketrue .

Bisa juga digunakan every(), tetapi harus menggilir setiap elemen dalam larik untuk memenuhi truehasil, sedangkan some()akan menebus segera setelah menemukan nilai yang tidak sama:

const equal = arr1test.every((val, idx) => val === arr2test[idx])

2

Saya memiliki nilai integer sederhana dalam proyek Game
Memiliki jumlah nilai yang lebih sedikit di setiap array, juga, membutuhkan array asli itu tidak tersentuh
Jadi, saya melakukan yang di bawah ini, itu berfungsi dengan baik. (Kode diedit untuk ditempel di sini)

var sourceArray = [1, 2, 3];
var targetArray = [3, 2, 1];

if (sourceArray.length !== targetArray.length) {
    // not equal
    // did something
    return false;
}

var newSortedSourceArray = sourceArray.slice().sort();
var newSortedTargetArray = targetArray.slice().sort();

if (newSortedSourceArray.toString() !== newSortedTargetArray.toString()) { // MAIN CHECK
    // not equal
    // did something
    return false;
}
else {
    // equal
    // did something
    // continued further below
}

// did some more work

return true;

Semoga membantu.


2

Menggunakan ES6

Kita akan menggunakan equalsfungsi Ramda , tetapi kita bisa menggunakan fungsi Lodash atau Underscore isEqual:

const R = require('ramda');

const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )

Dengan menggunakan opporator penyebaran, kami menghindari mutasi array asli, dan kami menjaga fungsi kami tetap murni.


2

Anda dapat menggunakan reducealih-alih loop agar terlihat pintar, tetapi dengan risiko rekan pengembang menganggap Anda sebagai orang yang cerdas.

function isArrayContentSame(a, b) {
  if (Array.isArray(a) && Array.isArray(b) && a.length == b.length) {
    a = a.concat().sort()
    b = b.concat().sort()
    return a.reduce((acc,e,i) => acc && e === b[i], true)
  } else {
    return false;
  }
}

1

Jika item dalam array bersifat primitif (angka atau karakter tunggal), Anda dapat menggunakan kombinasi perbandingan panjang, dan menggunakan set.

function equalArrayItems(arr1, arr2) {
  if (arr1.length !== arr2.length) return false
  const set1 = new Set(arr1)
  const set2 = new Set(arr2)
  const set3 = new Set(arr1, arr2)
  return set1.size === set3.size && set2.size === set3.size
}

1

Ini sudah tahun 2020 tetapi saya perhatikan bahwa sebagian besar solusi lain menggunakan sort, O (n * log n), menggunakan perpustakaan atau memiliki kompleksitas O (n ^ 2).

Berikut adalah solusi Javascript murni dengan kompleksitas linier, O (n):

/**
 * Check if two arrays of strings or numbers have the same values regardless of the order
 * @param {string[]|number[]} arr1
 * @param {string[]|number[]} arr2
 * @return {boolean}
 */    
compareArrays = (arr1, arr2) => {
    if (arr1.length !== arr2.length) return false;
    const lk1 = {};
    const lk2 = {};
    let i = arr1.length;
    while (--i >= 0) {
        lk1[arr1[i]] = true;
        lk2[arr2[i]] = true
    }
    i = arr1.length;
    while (--i >= 0) {
        const v = arr1[i];
        if (lk1[v] !== lk2[v]) return false;
    }
    return true
}

Tes:

compareArrays([2, 4], [4, 2]) => true
compareArrays([2, 4], [4, 2, 7]) => false
compareArrays([], []) => true

1
Hei, itu entri yang luar biasa! Ini cukup berbelit-belit tetapi masuk akal. Saya punya pertanyaan: Saya tidak terlalu paham dengan notasi Big O, tapi tentunya algoritma ini adalah O (2n)? Namun, jangan berpikir itu membuat banyak perbedaan.
Carlos Precioso

1
@CarlosPrecioso Itu benar dan O (2n) = O (n). Kompleksitas tidak berubah dikalikan dengan faktor konstan
SC1000

0

Jika Anda menggunakan Prototype Framework, Anda dapat menggunakan metode intersect dari sebuah array untuk mengetahui bahwa keduanya sama (terlepas dari urutannya):

var array1 = [1,2];
var array2 = [2,1];

if(array1.intersect(array2).length === array1.length) {
    alert("arrays are the same!");
}

Ini tidak berhasil - [1,2].intersect([1,2,3]).length === [1,2].lengthmengembalikan true. Anda juga harus membandingkan panjang array asli, saya telah mengedit postingan untuk didemonstrasikan.
GMA

Sebenarnya saya baru menyadari pengeditan yang saya sarankan tidak berfungsi dalam kasus duplikat ... misalnya akan mengembalikan false untuk array1 = [1,1,2]; array2 = [1,1,2];... jawaban asli tidak gagal untuk input itu.
GMA

Anda dapat melakukan yang sebaliknya dengan_.difference(array1, array2).length;
Vic

0

mohon periksa jawaban ini

var arr1= [12,18];
var arr2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
for(i=0;i<arr1.length;i++)
{
var array1=arr1[i];
for(j=0;j<arr2.length;j++)
{
    var array2=arr2[j];
    if(array1==array2)
    {
return true;
    }
}
}

2
Ini secara fungsional setara dengan jawaban ini , kecuali beberapa kesalahan. Pertama, ini semua harus dibungkus dalam suatu fungsi, atau returnkemauan tidak berpengaruh. Kedua, Anda harus memeriksa array yang diurutkan, karena [1,2]dan [2,1]akan dideteksi sebagai tidak sama. Ketiga dan yang paling penting, ini sebenarnya hanya akan memeriksa apakah beberapa elemen sama. Kondisionalnya harus if (array1!==array2) {return false;}. Mungkin ini bisa membantu Anda di masa depan!
Carlos Precioso

1
Dan sebagai komentar tambahan, coba gunakan indentasi untuk pemahaman yang lebih baik tentang aliran kode, serta nama variabel yang lebih jelas. Misalnya: array1dan array2bisa diganti namanya elem1dan elem2. Kedua tips ini akan menghemat banyak sakit kepala di masa mendatang!
Carlos Precioso

2
Pada pemeriksaan lebih lanjut, mengapa double loop? Kedua larik harus memiliki panjang yang sama, dan jika tidak, keduanya secara langsung tidak sama. Dengan cara ini Anda hanya dapat menggunakan satu loop. Saat ini, kode ini memeriksa apakah ada elemen dari larik pertama ada di mana saja di larik kedua. Periksa jawaban ini untuk melihat bagaimana Anda harus menerapkannya. Semoga berhasil dalam perjalanan JavaScript Anda!
Carlos Precioso

0

Menjawab setelah waktu yang lama tetapi berharap ini akan membantu seseorang yang mencari solusi sederhana dan pemula yang modern.

Sekarang kita dapat mencapai ini menggunakan banyak pustaka seperti lodash,, underscoredll. (Ini menjadi bagian dari proyek saat ini karena kesederhanaan, banyak fitur dan penggunaan yang tinggi)

Anda dapat menggunakan persimpangan dari perpustakaan lodash.

_.intersection(['2-1', '1'], ['2-2', '3-1', '2-1']); 
// => ['2-1']

Ini akan bekerja untuk semua tipe data ..


0

Jika Anda ingin membandingkan dua larik dan memeriksa apakah ada objek yang sama di kedua larik itu akan berhasil. Contoh:

Larik1 = [a, b, c, d]
Larik2 = [d, e, f, g]

Di sini, 'd' umum di kedua larik sehingga fungsi ini akan mengembalikan nilai sebenarnya.

  cehckArray(array1, array2) {
    for (let i = 0; i < array1.length; i++) {
      for (let j = 0; j < array2.length; j++) {
        if (array1[i] === array2[j]) {
          return true;
        }
      }
    }
    // Return if no common element exist 
    return false;
  }

0

Coba ini

function arraysEqual(arr1, arr2){
    if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length!=arr2.length)
        return false;

    return arr1.length==arr1.filter(word => arr2.includes(word)).length;
}

0

Saya memiliki cara lain berdasarkan jawaban yang diterima.

function compareArrays(array1, array2) {

    if (
        !Array.isArray(array1)
        || !Array.isArray(array2)
        || array1.length !== array2.length
    ) return false;

    var first = array1.sort().map(value => (String(value))).join();
    var second = array2.sort().map(value => (String(value))).join();

    return first == second ? true : false;
}

Hai, selamat datang di StackOverflow! Meskipun jawaban ini akan berhasil dalam beberapa kasus, akan ada beberapa kasus tertentu yang tidak berhasil. Pertama, perhatikan bahwa .sort () mengubah larik asli. Saat ini hal itu dianggap kurang higienis, itulah mengapa jawaban asli melakukan .concat () terlebih dahulu, untuk membuat salinan.
Carlos Precioso

Dan poin kedua, ini tidak akan bekerja secara konsisten dengan JavaScript lainnya. {foo: "bar"} === {foo: "bar"} mengembalikan nilai salah (mereka adalah dua objek berbeda yang dibuat secara terpisah); jadi bandingkanArrays ([{foo: "bar"}], [{foo: "bar"}]), juga harus mengembalikan false untuk konsistensi. Namun, dengan implementasi Anda, ini mengembalikan nilai true, karena representasi string dari objek adalah sama. Itu bisa menjadi perilaku yang diinginkan, atau tidak, tetapi perilaku yang harus diperhatikan dalam hal apa pun.
Carlos Precioso

0

Fungsi untuk membandingkan dua Array, untuk memeriksa apakah keduanya memiliki elemen yang sama. Bahkan jika mereka rusak ...

Ini bagus untuk array sederhana. [String, Number, Boolean, null, NaN].

Saya tidak menggunakan .sort (), itu memodifikasi array asli. Ada yang bilang itu buruk ...

Peringatan. Fungsi ini terbatas sehingga tidak dapat membandingkan Objek "[], {}" atau fungsi di dalam Array ini, array itu sendiri adalah Objek.

   let arraysHasSameElements = (arr1, arr2) => {
        let count =
            // returns counting of occurrences.
            (arr, val) => arr.reduce((count, curr) => (curr === val ? 1 : 0) + count, 0);

        /* this will return true if lengths of the arrays is equal.
           then compare them.*/
        return arr1.length === arr2.length

            // compare arr1 against arr2.
            && arr1.reduce((checks, val) =>

                /*  creating array of checking if a value has equal amount of occurrences
                    in both arrays, then adds true 'check'. */
                checks.concat(count(arr1, val) === count(arr2, val)), [])

                // checking if each check is equal to true, then .every() returns true.
                .every(check => check);
    }

    let arr1 = ['',-99,true,NaN,21,null,false,'help',-99,'help',NaN], 
        arr2 = [null,-99,'',NaN,NaN,false,true,-99,'help',21,'help'];
    arraysHasSameElements(arr1, arr2); //true

    let arr3 = [false,false,false,false,false,false], 
        arr4 = [false,false,false,false,false,false]
    arraysHasSameElements(arr3, arr4); //true


    // here we have uncommented version.
    let arraysHasSameElements = (arr1, arr2) => {
        let count = (arr, val) => arr.reduce((count, curr) => (curr === val ? 1:0) + count, 0);
        return arr1.length === arr2.length && arr1.reduce((checks, val) =>
            checks.concat(count(arr1, val) === count(arr2, val)), []).every(check => check);
    }

-1

Solusi Sederhana untuk membandingkan dua larik:

var array1 = [2, 4];
var array2 = [4, 2];

array1.sort();
array2.sort();

if (array1[0] == array2[0]) {
    console.log("Success");
}else{
    console.log("Wrong");
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.