2010-07-04 3 views
0

У меня есть массив элементов (terms), которые будут введены в <option> тегах в <select> Если какие-либо из этих элементов находятся в другом массиве (termsAlreadyTaking), они должны быть удалены первым Вот как я сделал это:..Лучший способ увидеть, содержит ли массив объект?

// If the user has a term like "Fall 2010" already selected, we don't need that in the list of terms to add. 
    for (var i = 0; i < terms.length; i++) 
    { 
     for (var iAlreadyTaking = 0; iAlreadyTaking < termsAlreadyTaking.length; iAlreadyTaking++) 
     { 
      if (terms[i]['pk'] == termsAlreadyTaking[iAlreadyTaking]['pk']) 
      { 
       terms.splice(i, 1); // remove terms[i] without leaving a hole in the array 
       continue; 
      } 
     } 
    }  

есть ли лучший способ сделать это? он чувствует себя немного неуклюжим.

Я использую JQuery, если это делает разницу.

UPDATE на основании ответа @Matthew Flaschen в :

// If the user has a term like "Fall 2010" already selected, we don't need that in the list of terms to add. 
var options_for_selector = $.grep(all_possible_choices, function(elem) 
          { 
           var already_chosen = false; 
           $.each(response_chosen_items, function(index, chosen_elem) 
           { 
            if (chosen_elem['pk'] == elem['pk']) 
            { 
             already_chosen = true; 
             return; 
            } 
           }); 
           return ! already_chosen; 
          }); 

Причина становится немного более многословным в середине, что $.inArray() возвращается ложь, потому что дубли я ищу не строго равны друг другу в == смысле. Однако все их значения одинаковы. Могу ли я сделать это более кратким?

+2

'splice' не совсем быстро. Возможно, было бы лучше добавить выбранные элементы в новый массив, а не удалить остальную часть из оригинала. – casablanca

ответ

3
var terms = $.grep(terms, function(el) 
      { 
       return $.inArray(el, termsAlreadyTaking) == -1; 
      }); 

Это до сих пор м * п производительность (т и п длины массивов), но это не должно быть большое дело до тех пор, пока они относительно невелики. Чтобы получить m + n, вы можете использовать хеш-таблицу

Обратите внимание, что ECMAScript предоставляет аналогичный массив. filter и Array. indexOf. Тем не менее, они еще не реализованы во всех браузерах, поэтому вам придется использовать реализации MDC как резерв. Поскольку вы используете jQuery, grep и inArray (который использует собственный indexOf, когда они доступны), проще.

EDIT:

Вы можете сделать:

var response_chosen_pk = $.map(response_chosen_items, function(elem) 
{ 
    return elem.pk; 
}); 
var options_for_selector = $.grep(all_possible_choices, function(elem) 
{ 
    return $.inArray(elem.pk, response_chosen_pk) == -1; 
}); 
+1

Поддерживает ли IE 'indexOf' на массивах? – Matchu

+0

Найдено - [работает во всех, кроме IE6] (http://stackoverflow.com/questions/143847/best-way-to-find-an-item-in-a-javascript-array/143863#143863). Вероятно, просто используйте '$ .inArray', чтобы избежать вопроса. – Matchu

+0

@ Мачу, ты прав. Я изменился на inArray (хотя вы могли бы использовать реализацию MDC как резерв). –

0

http://github.com/danstocker/jorder

Создать таблицу jOrder на termsAlreadyTaking, и индекс его с рк.

var table = jOrder(termsAlreadyTaking) 
    .index('pk', ['pk']); 

Тогда вы можете найти намного быстрее:

... 
if ([] == table.where([{ pk: terms[i].pk }])) 
{ 
    ... 
} 
... 
Смежные вопросы