2016-09-22 78 views
0

我創建一個函數,檢查兩個數組是否相同,我目前堅持檢查兩個對象(可能在一個數組內)是相同的。問題裏面for..in循環

解釋我的代碼一點點,我有一個名爲可變eq當函數結束,它應包含true對存在的第二陣列或在第一陣列中的每個元素所返回undefined如果一個元素沒有。

此外,我使用遞歸IIFE來檢查對象是否有子對象,並且子對象也是相同的。要檢查數組元素是否是對象字面量我使用el.constructor === Object

沒有百分之一百確定,我相信我在for..in循環中做了一些錯誤。

代碼:

function equals(a, b) { 
 
    return (a === b && a !== null) || (a.length === b.length && (function(a, b) { 
 
    var eq = []; 
 

 
    a.forEach(function(el1, index) { 
 
     b.forEach(function(el2) { 
 
     if (el1 === el2) eq[index] = true; 
 
     else if (el1.constructor === el2.constructor && el1.constructor === Object) { 
 
      /* a -> the object of the first array 
 
      * b -> the object of the second array 
 
      * c -> eq[index] then eq[index][i] provided how deep it goes */ 
 
      (function rec(a, b, c) { 
 
      c = []; 
 
      var i = 0; 
 
      for (var prop in a) { 
 
       for (var attr in b) { 
 
       if (prop === attr && a[prop] === b[attr]) c[i] = true; 
 
       else if (prop === attr && a[prop].constructor === b[attr].constructor 
 
        && a[prop].constructor === Object) { 
 
        rec(a[prop], b[attr], eq[index][i]); 
 
        } 
 
       } 
 
       i++; 
 
      } 
 
      })(el1, el2, eq[index]); 
 
     } 
 
     }); 
 
    }); 
 
    return /*!~eq.indexOf(undefined);*/ eq; 
 
    })(a, b)); 
 
} 
 

 
/* Use */ 
 
var a = [1, {a: "a", b: "b" }, 4, 6], 
 
    b = [{a: "a", b: "b"}, 1, 7, 6]; 
 

 
equals(a, b);


實施例1:(工作正常的簡單陣列)

var 
    a = [1, 3, 4, 6], 
    b = [3, 1, 7, 6]; 

equals(a, b); // returns: [true, true, undefined, true] 

實施例2:(不爲對象的工作)

var 
    a = [1, {a: "a", b: "b"}, 4, 6], 
    b = [{a: "a", b: "b"}, 1, 7, 6]; 

equals(a, b); /* returns: [true, undefined, undefined, true] 
       SHOULD return: [true, [true, true], undefined, true] */ 

任何幫助,將不勝感激。

+0

我敢肯定是比較兩個數組已經存在於許多庫和框架的一個功能。爲什麼重新發明輪子? –

+0

這是我的大學@HubertGrzeskowiak的練習:) –

+0

啊好的。你確定你想比較數組忽略元素的順序嗎? –

回答

0

休伯特·Grzeskowiak提到in his answer問題出在c沒有與eq[index]不得以任何連接。

一個快速的解決方案,我想出瞭解決問題刪除c = [],並宣佈eq[index][i]作爲它傳遞給rec時間數組作爲顯示在下面的代碼:

代碼:(只是IIFE)

(function rec(a, b, c) { 
    var i = 0; 
    for (var prop in a) { 
     for (var attr in b) { 
     console.log(i) 
     if (prop === attr && a[prop] === b[attr]) c[i] = true; 
     else if (prop === attr && a[prop].constructor === b[attr].constructor && 
      a[prop].constructor === Object) { 
       rec(a[prop], b[attr], (eq[index][i] = [])); // ← instead of eq[index][i] 
     } 
     } 
     i++; 
    } 
})(eachA, eachB, eq[index]); 
2

我認爲問題在於你的eq[index]被傳遞給比較函數。這不會傳遞引用,而只是一個未定義的值。通過在函數內設置c = [],您可以覆蓋未定義的新數組。無論如何,與eq都沒有關係。重新構建您的代碼,以便您可以在rec之外創建eq[index]中的數組,並將其傳入(c)。或者使功能rec返回一個值。

+0

感謝@Hubert,您的回答給了我一些不錯的思考。我發現一個解決方法是將'eq [index] [i]'**作爲數組傳遞給**'rec' **。 –

0

這是一個關於它的問題。代碼可以使用一些縮短,我沒有過度測試,但遞歸似乎適用於任何深度的嵌套內容。

var 
 
    a = [1, {a: "a", b: "b"}, 4, [1,{c:5,d:[1,2]}], 6], 
 
    b = [{a: "a", b: "b"}, [1,{c:5,d:[1,2]}], 1, 4, 6]; 
 

 
/* 
 
* returns 'true' if arrays are the same 
 
* 
 
* depends on 'checkObjects' 
 
*/ 
 
function checkArrays(arrayA, arrayB) { 
 
    if (arrayA === arrayB) return true; 
 
    if (arrayA === null || arrayB === null) return false; 
 
    if (arrayA.length !== arrayB.length) return false; 
 

 
    // since the order doesn't matter we sort the arrays 
 
    arrayA.sort(); 
 
    arrayB.sort(); 
 

 
    var arrayLength = arrayA.length; // stored for performance 
 
    for (var i = 0; i<arrayLength; i++) { 
 
     // if same value we continue through the array 
 
     // else they are not the same and we can stop 
 
     if (typeof arrayA[i] === 'object' && typeof arrayB[i] === 'object') { 
 
      if (!checkObjects(arrayA[i], arrayB[i])) { 
 
       return false; 
 
      } 
 
     } else if (typeof arrayA[i] === 'array' && typeof arrayB[i] === 'array') { 
 
      if (!checkArrays(arrayA[i], arrayB[i])) { 
 
       return false; 
 
      } 
 
     } else if (arrayA[i] !== arrayB[i]) { 
 
      return false; 
 
     } 
 
    } 
 
    // if we get here the values are equal 
 
    return true; 
 
} 
 

 
/* 
 
* returns 'true' if objects are the same 
 
* 
 
* depends on 'checkArrays' 
 
*/ 
 
function checkObjects(objectA, objectB) { 
 
    if (objectA === objectB) return true; 
 
    if (Object.keys(objectA).length !== Object.keys(objectB).length) return false; 
 

 
    var keys = Object.keys(objectA), 
 
     numberOfKeys = keys.length; // stored for performance 
 
    for (var i=0; i<numberOfKeys; i++) { 
 
     if (!(keys[i] in objectB)) { 
 
      return false; // objects don't have the same keys 
 
     } else { 
 
      if (!(objectA[keys[i]] === objectB[keys[i]])) { 
 
       // if same key-value-pairs exist we continue through the array 
 
       // else they are not the same and we can stop 
 
       if (typeof objectA[keys[i]] === 'array' && typeof objectB[keys[i]] === 'array') { 
 
        if (!checkArrays(objectA[keys[i]], objectB[keys[i]])) { 
 
         return false; 
 
        } 
 
       } else if (typeof objectA[keys[i]] === 'object' && typeof objectB[keys[i]] === 'object') { 
 
        if (!checkObjects(objectA[keys[i]], objectB[keys[i]])) { 
 
         return false; 
 
        } 
 
       } else { 
 
        return false; 
 
       } 
 
      } 
 
     } 
 
    } 
 
    // if we get here the key-value-pairs are equal 
 
    return true; 
 
} 
 

 
console.log(checkArrays(a, b));