2016-09-22 58 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));