É possível obter o índice que você está classificando em Underscore.js?

88

Estou usando a biblioteca JS Underscore e, em particular, usando as chamadas de biblioteca _.eache _.sortby. Estou me perguntando se há alguma maneira possível de obter o índice do valor dentro do representante do iterador

_.sortBy([1, 4, 2, 66, 444, 9], function(num){ 
    /*It'd be great to have access to the index in here */
    return Math.sin(num); 
});
contactmatt
fonte

Respostas:

163

O índice está realmente disponível como;

_.sortBy([1, 4, 2, 66, 444, 9], function(num, index){  });
Osoner
fonte
Funciona para o mapa de Lodash também
Csaba Toth
6
Infelizmente, isso realmente não funciona no Lodash's a sortBypartir da versão 4.17.4, o que provavelmente é mais útil saber neste cenário.
Jonathan Dumaine
81

Você pode obter o índice da iteração atual adicionando outro parâmetro ao seu iterador function, por exemplo

_.each(['foo', 'bar', 'baz'], function (val, i) {
    console.log(i + ": " + val); // 0: foo, 1: bar, 2: baz
});
jabclab
fonte
19

Se você preferir transformar sua matriz, o iteratorparâmetro da mapfunção de sublinhado também é passado para o índice como um segundo argumento. Assim:

_.map([1, 4, 2, 66, 444, 9], function(value, index){ return index + ':' + value; });

... retorna:

["0:1", "1:4", "2:2", "3:66", "4:444", "5:9"]
Martin Dow
fonte
10

O iterador de _.eaché chamado com 3 parâmetros (element, index, list). Então sim, para_.each você pode obter o índice.

Você pode fazer o mesmo em sortBy

Janith
fonte
6

Acho que vale a pena mencionar como o _.each () do Underscore funciona internamente. O _.each (list, iteratee) verifica se a lista passada é um objeto de matriz ou um objeto.

No caso de a lista ser uma matriz, os argumentos do iteratário serão um elemento da lista e um índice como no exemplo a seguir:

var a = ['I', 'like', 'pancakes', 'a', 'lot', '.'];
_.each( a, function(v, k) { console.log( k + " " + v); });

0 I
1 like
2 pancakes
3 a
4 lot
5 .

Por outro lado, se o argumento de lista for um objeto, o iteratário pegará um elemento de lista e uma chave:

var o = {name: 'mike', lastname: 'doe', age: 21};
_.each( o, function(v, k) { console.log( k + " " + v); });

name mike
lastname doe
age 21

Para referência, este é o código _.each () de Underscore.js 1.8.3

_.each = _.forEach = function(obj, iteratee, context) {
   iteratee = optimizeCb(iteratee, context);
   var i, length;
   if (isArrayLike(obj)) {
      for (i = 0, length = obj.length; i < length; i++) {
         iteratee(obj[i], i, obj);
      }
   } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i < length; i++) {
         iteratee(obj[keys[i]], keys[i], obj);
      }
   }
   return obj;
};
Mszymulanski
fonte
1

De maneira mais geral, na maioria das circunstâncias, as funções de sublinhado que recebem uma lista e um argumento como os dois primeiros argumentos fornecem acesso ao índice da lista como o penúltimo argumento do iterador. Esta é uma distinção importante quando se trata de duas funções de sublinhado, _.reduce e _.reduceRight, que usam 'memo' como seu terceiro argumento - no caso desses dois, o índice não será o segundo argumento, mas o terceiro:

var destination = (function() {
    var fields = ['_333st', 'offroad', 'fbi'];
    return _.reduce(waybillInfo.destination.split(','), function(destination, segment, index) {
        destination[fields[index]] = segment;
        return destination;
    }, {});
})();

console.log(destination);            
/*
_333st: "NYARFTW  TX"
fbi: "FTWUP"
offroad: "UP"

The following is better of course but not demonstrate my point:
var destination = _.object(['_333st', 'offroad', 'fbi'], waybillInfo.destination.split(','));
*/

Então, se você queria você poderia obter o índice usando sublinhado si: _.last(_.initial(arguments)). Uma possível exceção (eu não tentei) é _.map, pois ele pode pegar um objeto em vez de uma lista: "Se lista for um objeto JavaScript, os argumentos do iterador serão (valor, chave, lista)." - consulte: http://underscorejs.org/#map

Dexygen
fonte
0

Quando disponível, acredito que a maioria das funções do array lodash mostrará a iteração. Mas a classificação não é realmente uma iteração da mesma maneira: quando você está no número 66, não está processando o quarto item no array até que ele esteja concluído. Uma função de classificação personalizada fará um loop em uma matriz várias vezes, empurrando os números adjacentes para frente ou para trás, até que tudo esteja em seu devido lugar.

Sir_Mapsalot
fonte