【问题标题】:Better way to see if an array contains an object?查看数组是否包含对象的更好方法?
【发布时间】:2010-07-04 05:07:53
【问题描述】:

我有一个项目数组(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() 返回 false,因为我正在寻找的重复项在 == 意义上并不严格相等。但是,它们的所有值都是相同的。我可以让这个更简洁吗?

【问题讨论】:

  • splice 并不是很快。最好将所选项目添加到新数组中,而不是从原始数组中删除其余部分。

标签: javascript arrays object


【解决方案1】:
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)更容易。

编辑:

你可以这样做:

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

【讨论】:

  • IE 是否支持数组上的indexOf
  • 找到了 - works in all but IE6。应该只使用$.inArray 来避免这个问题。
  • @Matchu,你是对的。我改为 inArray(尽管您也可以使用 MDC 实现作为后备)。
  • @Matchu, indexOf 不适用于 any IE 版本上的 Array 对象,它刚刚在 IE9 Platform Preview 3 上实现,看起来很有希望...
  • @CMS - 嗯,我也是这么想的,但是链接的答案说的不同。猜猜我们发现自己有错误 - 谢谢:)
【解决方案2】:

http://github.com/danstocker/jorder

在 termsAlreadyTaking 上创建一个 jOrder 表,并用 pk 对其进行索引。

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

然后你可以更快地搜索:

...
if ([] == table.where([{ pk: terms[i].pk }]))
{
    ...
}
...

【讨论】:

    猜你喜欢
    • 2021-10-01
    • 2020-06-07
    • 2012-04-18
    • 2010-10-08
    • 2021-08-12
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    相关资源
    最近更新 更多