更有效的阵列搜索

时间:2015-01-08 01:17:12

标签: javascript arrays

我想根据该对象的唯一属性(即一个键)从对象数组中提取特定对象。

在下文中,我正在搜索' arr'密钥是8。

var myElement = arr.filter(function(element) {
  return element.key === 8;
});

这样可行,但每次运行时,即使找到了正确的元素,它也会迭代遍历数组中的所有元素。例如,如果它在索引4处找到myElement,但是数组中有100个元素,则该代码段的运行速度比其需要的数量多25倍。

是否有更有效的方法,或找到myElement时终止filter()的方法?

我觉得我错过了一些明显的东西......

5 个答案:

答案 0 :(得分:2)

您实际上需要一个find函数,该函数在找到第一个匹配项时返回。如果您使用的是ECMAScript 6规范,则可以使用Array.prototype.find,或者您可以实现一个简单的find

function find8(arr) {
    // type checks skipped for brevity
    var i = 0,
        j = arr.length;

    for (; i < j; i++) {
        if (arr[i].key === 8) {
            return arr[i];
        }
    }

    throw new Error('Not found');
}

如果你想要一个更通用的解决方案来接受谓词(即functions返回一个布尔值),你可以编写一个更通用的函数,如:

function find(arr, predicate) {
    // Again, type checks skipped for brevity
    var i = 0,
        j = arr.length;

    for (; i < j; i++) {
        // Note the condition is now a call to the predicate function
        if (predicate(arr[i])) {
            return arr[i];
        }
    }

    throw new Error('Not found');
}

答案 1 :(得分:1)

for (var i=0; i<arr.length; i++) {
    if (arr[i].key === 8) {
        console.log('FOUND ITEM AT KEY '+8);
        break;
    }
}

答案 2 :(得分:1)

听起来你最好用这样的东西:

function findByKey(items, key) {
    for (var index = 0; index < items.length; index++) {
        var item = items[index];
        if (item.key === key) {
            return item;
        }
    }
    return null;
}

请注意,如果您的列表已排序,您可以通过执行二进制搜索来改进它。虽然我个人建议散列(假设相同的密钥不会被使用两次)。类似的东西:

var array = [/* your data here... */];
var map = {};

//do this once; or once each time your array changes
for (var index = 0; index < array.length; index++) {
    var item = array[index];
    map[item.key] = item;
}

//now find things by doing this
var itemWithKey8 = map[8];

答案 3 :(得分:1)

我通过一个简单的for循环来处理这个问题(使用了一个通用的重用函数):

function findObject(arr, cond)
    for (i = 0; i < arr.length; i++) {
        if (cond(arr[i]){
            return arr[i];
        }
    }
}

// now call fincObject(myArray, function(element){element.key === 8})

或者,如果您知道要多次这样做,请创建一个应该很多的映射:

function makeMapping(arr, keyFunc){
    var mapping = {};
    for (var i = 0; i < arr.length; i++) {
        mapping[keyFunc(arr[i])] = arr[i];
    }
    return mapping;
}

这将返回一个对象映射8到具有key.id === 8的对象。您的keyFunc将是:

function keyFunc(element){
    return element.key;
}

答案 4 :(得分:0)

为什么重新发明轮子?这里有很多类似的答案,所以我会分享一种不同的方法 - 到目前为止我最喜欢的方法。有一个很棒的库linq.js(独立和jQuery插件版本),它使搜索,过滤,排序等变得轻而易举。

var myElement = Enumerable.From(arr).FirstOrDefault(null,         function(element) {
      return element.key === 8;
});

在上面的示例中,返回与条件匹配的第一个元素。如果未找到任何内容,则返回null(第一个参数是要返回的默认值)。