Оценка массивов Javascript - PullRequest
       18

Оценка массивов Javascript

3 голосов
/ 07 апреля 2010

У меня есть массив, который содержит массив массивов, если это имеет смысл. так например:

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

Я хочу посмотреть, существует ли массив внутри массива, поэтому, если [1, 2, 3] вообще дублируется. Я пытался использовать метод .indexOf, но он находит дубликат. Я также пытался Extjs вручную перебрать массив и оценить каждый внутренний массив, вот как я это сделал:

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

Это также не обнаруживает дубликат. console.log выведет [1, 2, 3] и [1, 2, 3], но не распознает их как равные. Я также попробовал === оценщик, но, очевидно, так как == не работает === не будет работать. Я в конце концов, любые предложения.

Ответы [ 7 ]

10 голосов
/ 07 апреля 2010

Сравнение двух массивов с использованием == или === не будет работать, поскольку они не являются одним и тем же объектом. Если вы хотите определить поэлементное равенство двух массивов, вам нужно сравнить массивы поэлементно.

Я сомневаюсь, что вы получите что-нибудь от использования трюков, подобных join(','), а затем от строковых операций Следующее должно работать, хотя:

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);
3 голосов
/ 07 апреля 2010

Я часто обнаруживал, что лучший способ сравнить два массива - сравнить их значения объединения.

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

Кроме того, вы можете добавить еще одну проверку:

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

Если проверка длины признана недействительной, это действительно быстрый способ сделать недействительным сравнение и не беспокоиться о выполнении объединений, но проверка также повышает надежность сравнения.Например, без проверки длины следующие массивы будут давать тот же результат при соединении:

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

С проверкой длины вы уверены, что что-то подобное не может произойти, и не имеетбеспокоиться об экранировании или чем-то еще ...

2 голосов
/ 07 апреля 2010

К сожалению, в общем случае единственный способ определить, равны ли массивы в этом смысле, - это сравнить их элементы.Там нет быстрого или встроенного способа сделать это.

В некоторых особых случаях вы можете сделать вашу жизнь немного проще, используя Array#join и сравнивая полученные строки, например:

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

... потому что a.join(",") приводит к строке "1,2,3", как и b.join(",").Но очевидно, что вы можете сделать это только тогда, когда знаете, что можете объединять и сравнивать значения по смыслу.Это может быть (, может ) быстрее, потому что вы можете использовать внутренние методы интерпретатора JavaScript join и методы сравнения строк, но, опять же, вы не можете сделать это в общем случае, только когда вы знаете данныев массиве все будет в порядке с превращением в строку и конкатенацией таким образом.

1 голос
/ 19 апреля 2011

Код в в этом ответе не различает примеры в:

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

Чтобы увидеть, что [null] и [,] действительно разные, рассмотрим:

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

, которые отображают null и undefined соответственно.


Составной массив может проверять идентичность массива! с == для идентичных массивов!

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

отображает:

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

и

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

Пока я голосую за .toSource () (& Mozilla), простые массивы можно сравнивать с помощью JSON.

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

отображает false,true.


Еще одна морщина: круговые массивы. Сравнивать их сложно, вот где светится .toSource ().

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

отображает false,true (в FireFox).


Относительно эффективности машины: вычислительные затраты незначительны по сравнению с затратами, затраченными на человеческое время. Компьютеры здесь, чтобы уменьшить человеческий труд, а не наоборот. Действительно вычислительно дорогие и широко развернутые вычисления могут потребовать больших инвестиций в человеческий труд для достижения эффективности. Это не один из тех времен.

Простота .toSource () может окупиться, если установить FF как прагматичный подход к решению таких проблем, как этот. Масштаб проблемы часто означает принуждение окружающей среды и машин к решению проблемы, а не человеческому труду.

1 голос
/ 07 апреля 2010

Вам нужно написать вспомогательный метод, который сравнивает 2 массива элемент за элементом и использовать его вместо ===.

0 голосов
/ 07 апреля 2010

Одной из возможных альтернатив для изучения было бы использование Array.toSource ():

>>> [3, 2, 1].toSource() == [3, 2, 1].toSource()
true
0 голосов
/ 07 апреля 2010

В духе интересного вызова я написал следующую функцию. Он работает и обрабатывает простые случаи (массивы, объекты, числа, даты, функции и строки)

Примечание: если вы передадите ему что-то вроде {документа}, вы попадете в мир боли, но простые вещи сработают.

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!');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...