我需要与Underscore的find基本相同的功能,但结果是元素的索引(而不是元素本身)。
据我所知,Underscore的indexOf寻找一个值而不是一个函数。 jQuery的inArray函数也存在同样的问题。
我想出了以下实现,但我不确定它是最有效的:
function myIndexOf(arr, filter) {
var index;
$.each(arr, function (i, elt) { if (filter(elt)) { index=i; return false; } });
return index;
}
答案 0 :(得分:10)
_.findIndex
:
var characters = [
{ 'name': 'barney', 'age': 36, 'blocked': false },
{ 'name': 'fred', 'age': 40, 'blocked': true },
{ 'name': 'pebbles', 'age': 1, 'blocked': false }
];
_.findIndex(characters, function(chr) {
return chr.age < 20;
});
// → 2
_.findIndex(characters, { 'age': 36 });
// → 0
_.findIndex(characters, { 'name': 'dino' });
// → -1 (not found)
答案 1 :(得分:5)
这是一个简单的实现:
function find(collection, filter) {
for (var i = 0; i < collection.length; i++) {
if(filter(collection[i], i, collection)) return i;
}
return -1;
}
它适用于任何具有length属性的可索引对象,您可以传递filter(element, index, collection)
形式的复杂过滤函数(可选参数)。
答案 2 :(得分:5)
Underscore使用以下实现:
_.find = function(obj, iterator, context) {
var result;
_.any(obj, function(value, index, list) {
if(iterator.call(context, value, index, list)) {
result = value;
return true;
}
});
return result;
}
这反过来调用_.any
,调用_.each
,调用Array.prototype.forEach
。效率并不完全是游戏的名称。它更多的是实用性。
如果你知道你正在处理一个数组或类似数组的对象,你可以使用@ Thor84no的解决方案,只需循环遍历数组,直到满足你的过滤条件。如果没有,你也可能正在处理对象,我只需将_.find重写为_.findIndex并使用result = index;
。
答案 3 :(得分:3)
您可以使用局部变量来实现:
var idx = 0;
var match = _.detect(my_list, function(itm){
return itm.something == some_test_value || ++idx == my_list.length && (idx = -1);
}
中提琴。你得到了索引和匹配值。如果迭代器到达结尾,则索引变为-1,如果匹配,则会在该索引上短路。
答案 4 :(得分:2)
自己进行for循环会更有效,并且在找到索引后使用break;
(或return
)离开循环。
for (var i = 0; i < arr.length; i++) {
if (filter(arr[i])) {
return i;
}
}