repetidos - javascript indexof array of objects
¿Hay un indexOf en javascript para buscar una matriz con función de comparación personalizada? (8)
Necesito el índice del primer valor en la matriz, que coincide con una función de comparación personalizada.
El underscorej muy agradable tiene una función de "búsqueda" que devuelve el primer valor donde una función devuelve verdadero, pero necesitaría esto que devuelva el índice. ¿Hay una versión de indexOf disponible en algún lugar, donde pueda pasar una función que se usa para comparar?
Gracias por cualquier sugerencia!
¿Qué tal tal función de encontrar?
(function () {
if (!Array.prototype._find) {
Array.prototype._find = function (value) {
var i = -1, j = this.length;
if (typeof(value)=="function")
for(; (++i < j) && !value(this[i]););
else
for(; (++i < j) && !(this[i] === value););
return i!=j ? i : -1;
}
}
}());
Aquí viene la versión en coffeescript del code de nrabinowitz.
# save a reference to the core implementation
indexOfValue = _.indexOf
# using .mixin allows both wrapped and unwrapped calls:
# _(array).indexOf(...) and _.indexOf(array, ...)
_.mixin ({
# return the index of the first array element passing a test
indexOf: (array, test) ->
# delegate to standard indexOf if the test isn''t a function
if (!_.isFunction(test))
return indexOfValue(array, test)
# otherwise, look for the index
for item, i in array
return i if (test(item))
# not found, return fail value
return -1
})
Como otros lo han señalado, lo suficientemente fácil como para rodar el tuyo, que puedes mantener corto y simple para tu caso de uso particular:
// Find the index of the first element in array
// meeting specified condition.
//
var findIndex = function(arr, cond) {
var i, x;
for (i in arr) {
x = arr[i];
if (cond(x)) return parseInt(i);
}
};
var moreThanTwo = function(x) { return x > 2 }
var i = findIndex([1, 2, 3, 4], moreThanTwo)
O si eres un CoffeeScripter:
findIndex = (arr, cond) ->
for i, x of arr
return parseInt(i) if cond(x)
El filtro de método de matriz de javascript devuelve un subconjunto de la matriz que devuelve verdadero de la función pasada.
var arr= [1, 2, 3, 4, 5, 6],
first= arr.filter(function(itm){
return itm>3;
})[0];
alert(first);
if you must support IE before #9 you can ''shim'' Array.prototype.filter-
Array.prototype.filter= Array.prototype.filter || function(fun, scope){
var T= this, A= [], i= 0, itm, L= T.length;
if(typeof fun== ''function''){
while(i<L){
if(i in T){
itm= T[i];
if(fun.call(scope, itm, i, T)) A[A.length]= itm;
}
++i;
}
}
return A;
}
Esta es la forma de subrayado para hacerlo: esto aumenta la función de subrayado principal con una que acepta una función de iterador:
// save a reference to the core implementation
var indexOfValue = _.indexOf;
// using .mixin allows both wrapped and unwrapped calls:
// _(array).indexOf(...) and _.indexOf(array, ...)
_.mixin({
// return the index of the first array element passing a test
indexOf: function(array, test) {
// delegate to standard indexOf if the test isn''t a function
if (!_.isFunction(test)) return indexOfValue(array, test);
// otherwise, look for the index
for (var x = 0; x < array.length; x++) {
if (test(array[x])) return x;
}
// not found, return fail value
return -1;
}
});
_.indexOf([1,2,3], 3); // 2
_.indexOf([1,2,3], function(el) { return el > 2; } ); // 2
Hay una función estándar en ECMAScript 2015 para Array.prototype.findIndex()
. Actualmente está implementado en todos los principales navegadores, además de Internet Explorer.
Aquí hay un polyfill, cortesía de la Red de Desarrolladores de Mozilla :
// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
if (!Array.prototype.findIndex) {
Object.defineProperty(Array.prototype, ''findIndex'', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError(''"this" is null or not defined'');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== ''function'') {
throw new TypeError(''predicate must be a function'');
}
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];
// 5. Let k be 0.
var k = 0;
// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return k.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return k;
}
// e. Increase k by 1.
k++;
}
// 7. Return -1.
return -1;
},
configurable: true,
writable: true
});
}
Podrías hacer algo como esto:
Array.prototype.myIndexOf = function(f)
{
for(var i=0; i<this.length; ++i)
{
if( f(this[i]) )
return i;
}
return -1;
};
Con respecto al comentario de Christian: si reemplaza un método JavaScript estándar con uno personalizado con una firma diferente y una funcionalidad diferente, es probable que ocurra algo malo. Esto es especialmente cierto si está utilizando bibliotecas de terceros que pueden depender del original, por ejemplo, Array.proto.indexOf. Así que sí, probablemente quieras llamarlo otra cosa.
Usando el guión bajo, se me ocurrió algo copiado de su implementación de búsqueda utilizando _.any:
findIndex = function (obj, iterator, context) {
var idx;
_.any(obj, function (value, index, list) {
if (iterator.call(context, value, index, list)) {
idx = index;
return true;
}
});
return idx;
};
¿Qué piensas? ¿Tienes mejores soluciones?