最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Evaluating Javascript Arrays - Stack Overflow

programmeradmin4浏览0评论

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.

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.

Share Improve this question asked Apr 7, 2010 at 12:18 StevenMcDStevenMcD 17.5k12 gold badges44 silver badges55 bronze badges 1
  • 1 You actually just have an array of arrays. An array that contains an array of arrays would require an extra set of square brackets. – tloflin Commented Apr 7, 2010 at 18:40
Add a ment  | 

7 Answers 7

Reset to default 10

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

I've often found that the best way to pare two arrays is to pare 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 parison and not bother with doing the joins, but the check also improves the reliability of the parison. 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...

Unfortunately, in the general case, the only way you can tell if arrays are equal in this sense is to pare 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 paring 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 pare the values meaningfully like that. Doing this may (may) be faster because you can leverage the JavaScript interpreter's internal join and string parison 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.

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

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 posited array can check array identity! with == for identical arrays!

 javascript:
      ra=[1,2,3]; ar=[4]; r=[]; posite=[ar,r,ra,ar,ra];
      for(i in posite)
         if(posite[i]==ra)
            alert( JSON.stringify(posite) +' 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 pared 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 putational expense is marginal pared to the cost invested in human time. Computers are here to reduce human labour, not the other way around. Truly putationally expensive and extensively deployed putations 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.

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

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

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 pare(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(!pare(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(!pare(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(pare(foo, bar)){
  alert('same!');
} else {
  alert('diff!');
}
发布评论

评论列表(0)

  1. 暂无评论