Pergunta

Eu gostaria de filtrar uma série de itens usando o map() função.Aqui está um trecho de código:

var filteredItems = items.map(function(item)
{
    if( ...some condition... )
    {
        return item;
    }
});

O problema é que os itens filtrados ainda ocupam espaço na matriz e eu gostaria de eliminá-los completamente.

Qualquer ideia?

EDITAR:Obrigado, esqueci filter(), o que eu queria é na verdade um filter() então uma map().

EDITAR2:Obrigado por apontar isso map() e filter() não são implementados em todos os navegadores, embora meu código específico não tenha sido planejado para ser executado em um navegador.

Foi útil?

Solução

Você deve usar o filter método em vez de map, a menos que você queira alterar os itens da matriz, além da filtragem.

por exemplo.

var filteredItems = items.filter(function(item)
{
    return ...some condition...;
});

[Editar:Claro que você sempre pode fazer sourceArray.filter(...).map(...) para filtrar e transformar]

Outras dicas

Escrevi uma resposta há algum tempo e minhas opiniões mudaram.Eu recomendo dar uma olhada no meu postagem no blog o que expande este tópico e o explica muito melhor.Também fornece uma comparação JSperf no final das alternativas.

dr é este:Para realizar o que você está pedindo (filtragem e mapeamento dentro de uma chamada de função), você deve usar Array.reduce().No entanto, o mais legível e geralmente mais rápido2 abordagem é apenas usar filtro e mapa encadeados:

[1,2,3].filter(num => num > 2).map(num => num * 2)

O que se segue é uma descrição de como Array.reduce() funciona e como ele pode ser usado para realizar filtros e mapas em uma iteração.Se estiver muito condensado, recomendo fortemente ver a postagem do blog com link acima, que é uma introdução muito mais amigável com exemplos e progressão claros.

Você fornece um argumento para reduzir que é uma função (geralmente anônima).

Essa função anônima leva dois parâmetros - um (como as funções anônimas passadas para map/filter/forEach) é o iterativo a ser operado.Há outro argumento para a função anônima passada para reduzir, porém, que essas funções não aceitam, e que é o valor que será repassado entre as chamadas de função, geralmente chamado de memorando.

Observe que enquanto Array.filter() aceita apenas um argumento (uma função), Array.reduce() também aceita um segundo argumento importante (embora opcional):um valor inicial para 'memo' que será passado para essa função anônima como seu primeiro argumento e, posteriormente, poderá ser modificado e transmitido entre chamadas de função.(Se não for fornecido, então 'memo' na primeira chamada de função anônima será, por padrão, o primeiro iteratee, e o argumento 'iteratee' será na verdade o segundo valor na matriz)

No nosso caso, passaremos um array vazio para começar e então escolheremos se injetaremos nosso iterativo em nosso array ou não com base em nossa função - este é o processo de filtragem.

Finalmente, retornaremos nosso 'array in progress' em cada chamada de função anônima, e a redução pegará esse valor de retorno e o passará como um argumento (chamado memo) para sua próxima chamada de função.

Isso permite que o filtro e o mapa aconteçam em uma iteração, reduzindo pela metade o número de iterações necessárias.:)

Para uma explicação mais completa, consulte MDN ou no link acima.:)

Exemplo básico de uma chamada de redução:

let array = [1,2,3];
const initialMemo = [];

array = array.reduce((memo, iteratee) => {
    // if condition is our filter
    if (iteratee > 1) {
        // what happens inside the filter is the map
        memo.push(iteratee * 2); 
    }

    // this return value will be passed in as the 'memo' argument
    // to the next call of this function, and this function will have
    // every element passed into it at some point.
    return memo; 
}, initialMemo)

console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)]

versão mais sucinta:

[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])

Observe que o primeiro iterado não era maior que um e, portanto, foi filtrado.Observe também o inicialMemo, nomeado apenas para deixar clara sua existência e chamar a atenção para ele.Mais uma vez, ele é passado como 'memorando' para a primeira chamada de função anônima e, em seguida, o valor retornado da função anônima é passado como argumento 'memorando' para a próxima função.

Outro exemplo de caso de uso clássico para memorando seria retornar o menor ou maior número em uma matriz.Exemplo:

[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
// ^this would return the largest number in the list.

Um exemplo de como escrever sua própria função de redução (acho que isso geralmente ajuda a entender funções como essas):

test_arr = [];

// we accept an anonymous function, and an optional 'initial memo' value.
test_arr.my_reducer = function(reduceFunc, initialMemo) {
    // if we did not pass in a second argument, then our first memo value 
    // will be whatever is in index zero. (Otherwise, it will 
    // be that second argument.)
    const initialMemoIsIndexZero = arguments.length < 2;

    // here we use that logic to set the memo value accordingly.
    let memo = initialMemoIsIndexZero ? this[0] : initialMemo;

    // here we use that same boolean to decide whether the first
    // value we pass in as iteratee is either the first or second
    // element
    const initialIteratee = initialMemoIsIndexZero ? 1 : 0;

    for (var i = initialIteratee; i < this.length; i++) {
        // memo is either the argument passed in above, or the 
        // first item in the list. initialIteratee is either the
        // first item in the list, or the second item in the list.
        memo = reduceFunc(memo, this[i]);
    }

    // after we've compressed the array into a single value,
    // we return it.
    return memo;
}

A implementação real permite acesso a coisas como o índice, por exemplo, mas espero que isso ajude você a ter uma ideia descomplicada da essência disso.

Não é isso que o mapa faz.Você realmente quer Matriz.filtro.Ou se você realmente deseja remover os elementos da lista original, precisará fazer isso imperativamente com um loop for.

Você deve notar, no entanto, que o Array.filter não é compatível com todos os navegadores, portanto, você deve prototipar:

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.filter)
{
    Array.prototype.filter = function(fun /*, thisp*/)
    {
        var len = this.length;

        if (typeof fun != "function")
            throw new TypeError();

        var res = new Array();
        var thisp = arguments[1];

        for (var i = 0; i < len; i++)
        {
            if (i in this)
            {
                var val = this[i]; // in case fun mutates this

                if (fun.call(thisp, val, i, this))
                   res.push(val);
            }
        }

        return res;
    };
}

E fazendo isso, você pode prototipar qualquer método que precisar.

Estou colocando esta resposta aqui porque os polyfills compartilhados nesta página são péssimos

function reduce(f, y, xs, context) {
  var acc = y;
  for (var i = 0, len = xs.length; i < len; i++)
    acc = f.call(context, acc, xs[i], i, xs);
  return acc;
}

function reduce1(f, xs, context) {
  if (xs.length === 0)
    throw Error('cannot reduce empty array without initial value');
  else
    return reduce(f, xs[0], xs.slice(1), context);
}

function map(f, xs, context) {
  return reduce(function(acc, x, i) {
    return acc.concat([
      f.call(context, x, i, xs)
    ]);
  }, [], xs);
}

function filter(f, xs, context) {
  return reduce(function(acc, x, i) {
    if (f.call(context, x, i, xs))
      return acc.concat([x]);
    else
      return acc;
  }, [], xs);
}

estender protótipos

if (Array.prototype.reduce === undefined) {
  Array.prototype.reduce = function(f, initialValue, context) {
    if (initialValue === undefined)
      return reduce1(f, this, context);
    else
      return reduce(f, initialValue, this, context);
  };
}

if (Array.prototype.map === undefined) {
  Array.prototype.map = function(f, context) {
    return map(f, this, context);
  };
}

if (Array.prototype.filter === undefined) {
  Array.prototype.filter = function(f, context) {
    return filter(f, this, context);
  };
}
var arr = [1,2,'xxx','yyy']

arr = arr.filter(function(e){ return e != 'xxx' });

arr  // [1, 2, "yyy"]
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top