JavaScriptで配列を比較する方法は?


988

2つのアレイを比較したい...理想的には、効率的に。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、2011年

55
2つの配列が同じになる理由は何ですか?同じ要素?同じ順序の要素ですか?JSONとしてのエンコードは、配列の要素をJSONにシリアル化できる場合にのみ機能します。配列にオブジェクトを含めることができる場合、どのくらい深く行きますか?2つのオブジェクトが「等しい」のはいつですか?
Felix Kling

48
@FelixKling、「平等」を定義することは間違いなく微妙なトピックですが、高水準言語からJavaScriptにアクセスする人にとって、のような愚かさの言い訳はありません([] == []) == false
Alex D

4
@AlexD配列は参照の等価性を使用しているように見えますが、これは予想どおりです。あなたがそれを行うことができなかったらそれはかなりひどいでしょう
JonnyRaa '29

3
@AlexD私はこれが起こらない言語をいくらか考えることができません。C ++では、2つのポインターを比較します-false。Javaでは、JavaScriptと同じことを行います。PHPでは、裏で何かが配列をループします。PHPを高水準言語と呼んでいますか?
トマーシュZato -復活モニカ

回答:


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;

しかし、文字列を比較する方がはるかに高速です-ループはありません...」と言うかもしれません。配列を文字列に変換する最初の再帰ループと、2つの文字列を比較する2番目のループ。したがって、この方法はstringを使用するよりも高速です

大量のデータは常にオブジェクトではなく配列に格納する必要があると思います。ただし、オブジェクトを使用する場合は、部分的に比較することもできます。
方法は次のとおりです。

オブジェクトの比較:

上で述べたように、2つのオブジェクトインスタンスは、たとえ現時点で同じデータが含まれていても、決して等しくなることはありません。

({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では、compareは通常、他のオブジェクトよりも大きいオブジェクトを示す署名付き整数を返します。参照:Comparer.Compare
オリバー

15
これは正しい方法であるだけでなく、かなり効率的でもあります。この質問で提案されたすべてのメソッド用に用意した簡単なjsperfスクリプトを次に示します。jsperf.com/comparing-arrays2
Tolga E

96
組み込み型のプロトタイプを変更することは間違いなく正しい方法で
Jasper

31
さらに、書き直しが簡単かどうかではなく、回答が悪い習慣と見なされているもの(developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…)を推奨すべきではなく、ヘッダー「正しい方法」の下では絶対にこれを行わないでください
Jasper

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リファレンス参照してください)。

更新

私がコメントから読んだものから、配列をソートして比較すると正確な結果が得られるかもしれません:

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 2013

13
それは@espertus、配列のいずれかの種類で動作ソートか
のMichałMiszczyszyn

36
はい、正確に。この関数は2つの配列を比較することになっています。それらが並べ替えられているかどうかは関係ありません。連続する要素は等しい必要があります。
のMichałMiszczyszyn

22
@espertus確かに、両方の配列で要素の順序がまったく同じでない場合、trueは返されません。ただし、等価性チェックの目的は、同じ要素が含まれているかどうかをチェックすることではなく、同じ順序で同じ要素が含まれているかどうかをチェックすることです。
2016

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 2017年

5
順序が重要でない場合は、このチェックの前に配列をソートできます_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
Filype

最も簡潔で簡単な答えIMHO :-)
キーランライアン

121

これは、JSON文字列化を使用してこれを行う最も簡単な方法だと思います。状況によっては、これが最良の解決策になる場合があります。

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

これにより、オブジェクトa1a2文字列が比較できるように変換されます。上記の回答のいずれかに示されているソートアルゴリズムを使用してオブジェクトをソートできるため、ほとんどの場合、順序は重要です。

オブジェクトを比較するのではなく、オブジェクトの文字列表現を比較していることに注意してください。それはあなたが望むものではないかもしれません。


良い答えですが、なぜ[] == [] falseを返すのですか?どちらも単純なオブジェクトですが、なぜですか?
Pardeep Jain

4
@PardeepJain、これは、デフォルトで、ECMAScript for Objectsの等価演算子が同じメモリロケーションを参照するとtrueを返すためです。var x = y = []を試してください。//等価性はtrueを返します。
radtek、2016年

7
JSON文字列化関数は高速ではないことに注意してください。より大きな配列で使用すると、確実に遅れが生じます。
Lukas Liesis

6
この質問では特に、JSON.stringifyを使用するよりも良い/速い方法があるかどうかを尋ねます。
ドンハッチ

状況によってはこれがなぜ良い解決策となるのかについて詳しく説明します。
radtek、2017年

61

「同一」の意味がわかりません。たとえば、配列ab以下は同じですか(ネストされた配列に注意してください)?

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:「同一」が何を意味するのかという質問からは不明です。明らかに、この回答は浅いチェックを行うだけです。メモを追加します。
Tim Down

これは、arrayIdentical([1、2、[3、2]]、[1、2、[3、2]])では失敗します。
Gopinath Shiva 2015

4
@GopinathShiva:まあ、それはあなたがそれが戻ることを期待している場合にのみ失敗しますtrue。答えはそうではないことを説明しています。ネストされた配列を比較する必要がある場合は、簡単に再帰チェックを追加できます。
Tim Down

59

実用的な方法

特定の実装が「間違った」ソリューションとは対照的に「正しい」(「正しい」)だけである場合、「The Right Way™」であると言うのは間違っていると思います。トマーシュのソリューションは、文字列ベースの配列比較よりも明らかに改善されていますが、それが客観的に「正しい」ことを意味するわけではありません。とにかく何が正しいですか?最速ですか?最も柔軟性がありますか?理解するのが最も簡単ですか?デバッグが最速ですか?最小限の操作を使用していますか?副作用はありますか?1つのソリューションがすべてのものの中で最高のものを持つことはできません。

トマシュは彼の解決策は速いと言えるかもしれませんが、私はそれが不必要に複雑であるとも言います。ネストされているかどうかにかかわらず、すべての配列で機能するオールインワンソリューションを目指しています。実際、入力として配列だけでなく、それでも「有効な」答えを出そうとします。


ジェネリックは再利用性を提供します

私の答えは別の方法で問題に取り組みます。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、および2つの入力配列、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定義できます(厳密な等価性のため)。arrayCompareab===

equal独自の関数として定義することにも注意してください。これは、arrayCompare別のデータ型(配列)のコンテキストで一次コンパレーターを利用するための高次関数としての役割を強調しています。


ゆるい比較

代わりに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

深い比較(再帰)

これは浅い比較だけであることに気づいたでしょう。きっとトマシュの解法は「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別段の比較abユーザ指定のコンパレータ(へf)。これにより、個々の要素を実際に比較する方法とは別に、深い比較動作を維持できます。つまり、上の例のように、我々は深く使用して比較することができequallooseEqualあるいは我々が作る任意の他のコンパレータ。

ので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

そのような単純な。ここではバニラJSオブジェクトを使用しましたが、このタイプのコンパレータはどのオブジェクトタイプでも機能します。カスタムオブジェクトも。この種の等価性テストをサポートするには、トマシュのソリューションを完全に作り直す必要があります

オブジェクトを含む深い配列?問題ない。汎用性の高い汎用関数を作成したため、さまざまなユースケースで機能します。

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それ自体については何も複雑ではなく、私たちが作成した各カスタムコンパレータは非常に単純な実装を持っています。

簡単に、我々は、2つの配列を比較することのために私たちが望む正確にどのように定義することができます-浅い、深い、厳格な、緩い、一部のオブジェクトのプロパティ、またはいくつかの任意の計算、またはこれらの任意の組み合わせ- すべてを1つの手順を使用してarrayCompare。たぶん、RegExpコンパレータを夢見てください!子供がこれらの正規表現をどのように愛しているか知っています…

最速ですか?いいえ。しかし、おそらくどちらかである必要はありません。コードの品質を測定するために使用される唯一の測定基準が速度である場合、非常に優れたコードの多くが破棄されます。そのため、このアプローチを実践的な方法と呼んでいます。それとも、より公正であると実用的な方法。この答えは他のいくつかの答えと比較して実用的であるとだけ言っているわけではないので、この説明はこの答えに適しています。それは客観的に真実です。推論が非常に簡単な非常に小さなコードで高度な実用性を達成しました。他のコードでは、この説明を得ていないと言うことはできません。

それはあなたにとって「正しい」解決策になりますか?それはあなたが決めることです。そして、他の誰もあなたのためにそれを行うことはできません。あなただけがあなたのニーズが何であるかを知っています。ほとんどすべての場合で、私は、賢くて速い種類よりも、単純で実用的で用途の広いコードを重視しています。何を評価するかは異なる可能性があるため、自分に合ったものを選択してください。


編集する

私の古い答えはarrayEqual、小さな手順に分解することにもっと焦点を当てていました。これは興味深い演習ですが、この問題に取り組むための最良の(最も実用的な)方法ではありません。興味があれば、この変更履歴を見ることができます。


8
「最高の種類のコードはコメントすら必要としない」...それを言うのは嫌いですが、このコードはコメントや別の名前を使用する可能性があります-「比較」はかなり曖昧です。私が正しく読んでいれば、あなたの「比較」は本質的にカリー再帰的な「すべて」です。おもう。それとも、カレー再帰的な「一部」ですか?うーん。これは必要以上に多くの考えを必要としています。おそらく、より良い名前は、「同値関係」の標準的な用語を利用した「arraysEquivalent」です。または、さらに明確に(とにかく私には)、「再帰的に同等」です。
ドンハッチ

1
@DonHatch返信する機会をありがとう。「比較する」とはどういう意味arrayCompareですか?はい、関数はカリー化されていますが、someおよびとは異なりeveryます。arrayCompareコンパレータと比較する2つの配列を受け取ります。任意の関数を使用して配列を比較できるため、具体的には総称名を選択しました。関数はカリー化されているため、新しい配列比較関数(などarrayEqual)の作成に特化できます。より良い名前を提案できますか?追加のコメントや説明が必要だと思う領域はどこですか?^ _ ^について
いただきます

1
私の要点はまだはっきりしていません-しかし私の要点は、あなたの関数は実際には任意の関数を取ることを意図していません、私は思いません-それは同値関係を取ることを意図して おり、それは同値関係を返します。それは重要です-私が言及したような他の種類の任意のバイナリ関数が与えられた場合、それは賢明なことを何もしません(私は思いません)、人々がしばしば「比較」と呼ぶものでさえ。したがって、「比較」の代わりに「同等」を名前に含めると役立つと思います。
ドンハッチ

1
@ftor、作者:非常に役立つ回答、素晴らしい仕事、+ 1。フィードバック:あなたは単純さを主張しますが、多くの開発者にとって、1行に3つの矢印が付いた式は単純または理解しにくいです。例:f =>([x、... xs])=>([y、... ys])=>。私はこれを常に使用しており、「ただ見るだけ」ではなく、精神的に分解しなければなりませんでした。2番目の点は正しいです、すべてを使用してください。あなたの理由を考慮しても、バランスをとることは私だけでなく、あなたのデザイン哲学を推測しようとするときのあなたの視点からも良いようです。
ホイットニーランド2017年

1
私はこれが学習の場所であることを理解していますが、ここでは、関数型のスタイルを研究する平均的なプログラマーがカリー化された関数をカリー化されていない関数に変換できると仮定します。私の答えは、このスタイルがあなた自身のプログラムで使用されることを意図していることを示唆していません-それをカリー化せずに書いて、あなた自身のインデントルールを使用して書いてください、あなたが好きなように書いてください-私は私が表現すると信じるスタイルで私の答えを書きます最高のプログラム。私はまた、私たちのプログラムを構文的に表現する方法に挑戦するよう他の人を招待し
たいと思います

54

元の質問の精神:

2つのアレイを比較したい...理想的には、効率的に特別なもの何もありません。それらが同一である場合は真、そうでない場合は偽です。

ここで提案されたいくつかのより単純な提案のパフォーマンステストを実行して、次の結果が得られました(速いから遅い)。

while(67%) by Tim Down

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

ユーザーごと(69%)

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

DEIによる削減(74%)

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

参加toString(78%) by Gaizka Allende&vivek

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

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

ハーフtoString(90%) by Victor Palomo

a1 == a2.toString();

radtekによる文字列化(100%)

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

アレイは、単一次元アレイをソートすることを前提としてい以下の実施例を。.length一般的なベンチマークの比較は削除されました(a1.length === a2.length提案のいずれかに追加すると、パフォーマンスが最大10%向上します)。それぞれの速度と制限を把握しているため、最適なソリューションを選択してください。

関連のないメモ:この質問への完全に正当な回答について、反対投票ボタンですべてのトリガーハッピーなJohn Waynesを目にするのは興味深いことです。


リンクは空のテストを開きます。
Alexander Abakumov

配列のサイズを大きくすると、これらの数値は適用されません(特に削減アプローチ)。Array.from({length: 1000}).map((a,v)=> $ {v}でお試しください.padStart(10,2));
ナラヨン

浅いアレイでのみ機能します
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;
}

この関数は、デフォルトでtrueになっているstrictの追加パラメーターを取ります。この厳密なパラメーターは、配列が内容とその内容の順序の両方で完全に等しい必要があるか、または単に同じ内容を含む必要があるかを定義します。

例:

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

配列の構造がどのように見えるかという質問には記載されていないので、配列内にネストされた配列もオブジェクトもないこと確実にわかっている場合(たまたま私に起こったので、私はこれに行きました)回答)上記のコードは機能します。

どうなるかというと、スプレッド演算子(...)を使用して両方の配列を連結し、次にSetを使用して重複を排除しています。それができたら、それらのサイズを比較できます。3つのアレイすべてが同じサイズであれば、問題ありません。

この回答は、要素の順序無視します。先ほど言ったように、正確な状況が私に起こったので、同じ状況の誰かがここに来るかもしれません(私がしたように)。


編集1。

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
これは特定のアレイでのみ機能し、大きなアレイでは非常に遅くなります。
トマーシュZato -復活モニカ

2
JSONの生成もループしています。あなたは(またはそう思われるだけで)知らないのです。ループのほかに、JSONの生成にはより多くのメモリも必要です。比較する前に、上記の配列の2つの文字列表現を作成します。downwote関数は、回答を最高から最低の順に並べるために実装されています。あなたの答えは良い答えではないと思いますので、私は反対票を投じました。
トマーシュZato -復活モニカ

2
申し訳ありませんが、私はJSONではなくと言いました.join()。おそらく、2番目のソリューションをプライマリとして(多次元配列に対しては歯が立たないものの、より優れたソリューションであるため)と述べた場合、私はそのように判断しません。これまでのところ、私は配列を文字列に変換するすべての回答を無視しました。同様に、あなたがそれを知る必要がある場合に備えて、私は正しい方法を使用するすべてのものを賛成しました。つまり、@ Tim Downの回答とBireysの回答です。
トマーシュZato -復活モニカ

6
最初のバージョンは失敗します: 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

あなたのようなテストフレームワークを使用している場合はモカチャイのアサーション・ライブラリを、あなたは使用することができ、深い比較アレイへの平等を。

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

これは、配列が対応するインデックスで等しい要素を持っている場合にのみtrueを返します。


6

数値または文字列のみの2つの配列の場合、これは1行の簡単なものです。

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( ''))// trueを返す
Dan M.

すべきではない:array1.join( '')は「1」、array2.join( '')は「11」
Gaizka Allende

すみません、タイプミス。最初の配列はでなければなりません[11]。これがなぜ起こるのか、そしてどのように修正するのかについてはかなり明白です。
Dan M.17年

[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])。また、文字列化が不要で、壊れやすく、間違っている理由については、このページの他の説明を参照してください。
上手に扱う

are_arrs_equal([1,2], [2,1])true期待どおりに戻ります。おそらくこのソリューションは理想的ではありませんが、私にとってはうまくいきました。
yesnik 16

これがまさに問題です。これら2つは、順序付けられたデータ構造の「等しい」という言葉の正気の意味では等しくありません。それらはセットではなく配列であり、セットの等価性が必要な場合は、それをそれと呼び、別の質問に答える必要があります。:-)
modをうまく処理する

1
上記のコメントに同意しますが、この解決策は、順序が重要ではない整数の単純な配列でも機能するため、使用します。
tomazahlin

1
失敗しare_arrs_match([1,2], ["1,2"])ます(戻り値true)。また、the sort()呼び出しによって入力配列変更されることに注意してください。これは望ましくない場合があります。
try-catch-finally

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

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

両方の配列に同じ要素があるが同じ順序ではない場合、コードはケースを適切に処理しません。

要素が数値である2つの配列を比較する例を使って私のコードを見てください。他の要素型に変更または拡張できます(.toString()の代わりに.join()を使用することにより)。

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

これは私がやった方法です。


良い解決策-しかし、特定のプリミティブや深くネストされた配列など、特定の状況では常に意図したとおりに機能しないのではないかと思いますか?私はそれがすべての状況でうまくいくことを願っています
ベン・ロンドー

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

===が配列に対して期待どおりに動作しないため、この答えは機能しません。
マイケルヤン

===はここでは重要ではありませんが、答えは機能します(sort()は配列でのみ機能するため)。==でも機能します。
Amay Kulkarni

自分で試してみてください。このコードを実行するとfalseが出力されます。これは、実際の値ではなく==と===の両方で配列の参照値を比較するためです。==および===は、プリミティブ型の比較のみを目的としています。
Michael Yang

これはtrueを返し、使用しましたが、不要なので「===」を削除しました
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のアイデアを拡張する。TomasのArray.prototype.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。あなたが与えた例でそれが「失敗」した場合、それは「失敗」のやや恣意的な定義の場合にのみ当てはまります。これらの2つの異なる配列が等しいと見なされるのはなぜでしょうか?ここで実装しようとしている「平等」の概念、またはそれが賢明または役立つものである理由を説明していませんが、多次元配列を1次元に縮小されているかのように比較したいようですもの。もしそうなら、あなたもそれを達成しませんでした:[1,2] .compare([[1,2]])は、トマシュのものと同じように、あなたのバージョンでfalseを与えます。
Mark Amery

私が推測できることに基づいて、彼は、[1、2、3、4]と[1、3、2、4]は等しいものとして比較する必要があると言っています(順序は関係ありません)。
Gautham Badhrinathan 2013

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 reduceおよびArray includeを使用):

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チェックにより、1つの配列の要素のセットが他の配列の単なるサブセットではないことが保証されます。

  • レデューサーは、1つの配列をウォークスルーして、他の配列の各項目を検索するために使用されます。1つのアイテムが見つからない場合、reduce関数はを返しますfalse

    1. 最初の例では、要素が含まれていることがテストされています
    2. 2番目の例も注文をチェックします

1
この答えを明確にするために、コードを少し説明していただけませんか?
2016年

1.配列の長さを比較して、1つの配列が他の配列のサブセットではないことを確認します
DEls

2.レデューサーを使用して1つの配列をウォークスルーし、他の配列の各項目を検索します。1つのアイテムが見つからない場合、reduce関数は「false」を返します
DEls

@DEls:説明を回答に編集しました(少し書き直して拡張)。これでコメントを削除して、最初のコメントとこのコメントに古いフラグを付けることができます。
try-catch-finally

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()を使用して2つの配列を比較できます。配列から文字列を作成し、2つの配列から取得した2つの文字列が等しいかどうかを比較します

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

で動作しますMULTIPLEと引数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.