Лучший способ увидеть, содержит ли массив объект? - PullRequest
0 голосов
/ 04 июля 2010

У меня есть массив элементов (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, если это имеет значение.

ОБНОВЛЕНИЕ На основании ответа @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 ]

3 голосов
/ 04 июля 2010
var terms = $.grep(terms, function(el)
            {
              return $.inArray(el, termsAlreadyTaking) == -1;
            });

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

. Обратите внимание, что ECMAScript предоставляет аналогичные Array. 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;
});
0 голосов
/ 15 июля 2010

http://github.com/danstocker/jorder

Создайте таблицу jOrder на TermsAlreadyTaking и проиндексируйте ее с помощью pk.

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

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

...
if ([] == table.where([{ pk: terms[i].pk }]))
{
    ...
}
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...