Evaluating Javascript Arrays

南楼画角 提交于 2020-05-15 07:36:25

问题


I have an array that contains an array of arrays if that makes any sense. so for example:

[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]

I want to see whether an array exists withing the array, so if [1, 2, 3] is duplicated at all. I have tried to use the .indexOf method but it does find the duplicate. I have also tried Extjs to loop through the array manually and to evaluate each inner array, this is how I did it:

var arrayToSearch = [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]];        
var newArray = [1, 2, 3];
Ext.each(arrayToSearch, function(entry, index){
                    console.log(newArray, entry);
                    if(newArray == entry){
                        console.log(index);
                    };
                });

This also does not detect the duplicate. the console.log will output [1, 2, 3] and [1, 2, 3] but will not recognize them as equal. I have also tried the === evaluator but obviously since == doesn't work the === wont work. I am at wits end, any suggestions.


回答1:


Comparing the two arrays using == or === will not work because they are not the same object. If you want to determine the element-wise equality of two arrays you need to compare the arrays element-wise.

I doubt you'll gain anything from using tricks like join(',') and then using string operations. The following should work though:

function arraysAreEqual (a, b) {
  if (a.length != b.length) {
    return false;
  }

  for (var i=0; i<a.length; i++) {
    if (a[i] != b[i]) {
      return false;
    }
  }

  return true;
}

function containsArray (arrays, target) {
  for (var i=0; i<arrays.length; i++) {
    if (arraysAreEqual(arrays[i], target)) {
      return true;
    }
  }

  return false;
}

var arraysToSearch = [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]];
var newArray = [1, 2, 3];
containsArray(arraysToSearch, newArray);



回答2:


I've often found that the best way to compare two arrays is to compare their join values.

if(newArray.join('/') == entry.join('/')) ...

Additionally, you may want to throw in one more check:

if(newArray.length == entry.length && newArray.join('/') == entry.join('/'))

If the length check is invalidated, that's a really quick way of invalidating the comparison and not bother with doing the joins, but the check also improves the reliability of the comparison. For instance, without the length check, the following arrays would yield the same result when joined:

var a = [1, '2/3'];
var b = [1, 2, 3];

With the length check, you're sure something like this can't happen, and don't have to worry about escaping delimiters or anything...




回答3:


Unfortunately, in the general case, the only way you can tell if arrays are equal in this sense is to compare their elements. There's no shortcut or built-in way of doing that.

In some special cases you can make your life a bit easier by using Array#join and comparing the resulting strings, e.g.:

var a = [1, 2, 3];
var b = [1, 2, 3];
alert(a.join(",") == b.join(",")); // Alerts "true"

...because a.join(",") results in the string "1,2,3", as does b.join(","). But obviously you can only do that when you know that you can concatenate and compare the values meaningfully like that. Doing this may (may) be faster because you can leverage the JavaScript interpreter's internal join and string comparison methods, but again, you can't do this in the general case, only when you know the data in the array is going to be okay with being turned into a string and concatenated like that.




回答4:


You need to write a helper method that compares 2 arrays element by element and use that instead of ===.




回答5:


The code in this answer fails to differentiate the examples in:

javascript:
function sameRAs(newArray,entry){
     return newArray.length == entry.length &&
                                  newArray.join('/') == entry.join('/')};
     alert( sameRAs(  [1,'2/3',4],  [1,2,'3/4']  )  ?  'same' : 'different' );
     alert( sameRAs(    [null],         [,]      )  ?  'same' : 'different' );

To see that [null] and [,] are indeed different, consider:

 javascript:  alert( [null][0] );  alert( [,][0] );

which display null and undefined respectively.


A composited array can check array identity! with == for identical arrays!

 javascript:
      ra=[1,2,3]; ar=[4]; r=[]; composite=[ar,r,ra,ar,ra];
      for(i in composite)
         if(composite[i]==ra)
            alert( JSON.stringify(composite) +' at ['+ i +']'+' == ['+ ra +']')

displays:

[[4],[],[1,2,3],[4],[1,2,3]] at [2] == [1,2,3]

and

[[4],[],[1,2,3],[4],[1,2,3]] at [4] == [1,2,3]

While my vote is with .toSource() (& Mozilla), simple valued arrays can be compared via JSON.

 javascript:
      ra=[1,2,3]; ar=[1,2,3];
      alert([  ra==ar,   JSON.stringify(ra)==JSON.stringify(ar)  ]);

displays false,true.


Another wrinkle: circular arrays. Comparing these is difficult, which is where .toSource() shines.

javascript:
   ra = [0,1,2];   ra[3] = ra;      r2d2 = #2= [0,1,2,#2#];
   alert([ ra==r2d2,  ra.toSource() == r2d2.toSource() ])

displays false,true (in FireFox).


Regarding machine efficiency: the computational expense is marginal compared to the cost invested in human time. Computers are here to reduce human labour, not the other way around. Truly computationally expensive and extensively deployed computations may warrant a large investment in human labour to realize efficiencies. This is not one of those times.

The simplicity of .toSource() might payoff by installing FF as a pragmatic approach to solving problems such as this. The scale of a problem often means coercing the environment and machinery to get a solution rather than using human labour.




回答6:


One possible alternative to explore would be using Array.toSource():

>>> [3, 2, 1].toSource() == [3, 2, 1].toSource()
true



回答7:


In the spirit of an interesting challenge, I wrote the following function. It works, and handles simple cases of (arrays, objects, numbers, dates, functions, & strings)

Note: If you pass it things like {document} you are in for a world of hurt, but the simple stuff works.

function compare(a,b){
  if(a instanceof Array && b instanceof Array){
    if(a.length != b.length){
      return false;
    }
    for(var i=0,l=a.length;i<l;i++){
      if(!compare(a[i], b[i])){
      return false;
      }
    }
    return true;
  } else if(typeof(a) == 'object' && typeof(b) == 'object'){
    var keys = {};
    for(var i in a){
      keys[i] = true;
      if(!compare(a[i], b[i])){
      return false;
      }
    }
    //what if b contains a key not in a?
    for(var i in b){
      if(!keys[i]){
      return false;
      }
    }
    return true;
  } else {
    return (a == b);
  }
}

var someDate = new Date();
var someFunc = function(){alert('cheese');};

var foo = {};
foo['a'] = 'asdf';
foo['b'] = 'qwer';
foo['c'] = 'zxcv';
foo['d'] = ['a','b','c','d','e'];
foo['e'] = someDate;
foo['f'] = 34;
foo['g'] = someFunc

var bar = {};
bar['a'] = 'asdf';
bar['b'] = 'qwer';
bar['c'] = 'zx' + 'cv';
bar['d'] = ['a','b','c','d','e'];
bar['e'] = someDate;
bar['f'] = 34;
bar['g'] = someFunc

if(compare(foo, bar)){
  alert('same!');
} else {
  alert('diff!');
}


来源:https://stackoverflow.com/questions/2592305/evaluating-javascript-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!