Por que a função de mapa javascript retorna indefinida?

112

Meu código

 var arr = ['a','b',1];
 var results = arr.map(function(item){
                if(typeof item ==='string'){return item;}  
               });

Isso dá os seguintes resultados

["a","b",undefined]

Não quero indefinido na matriz de resultados. Como posso fazer isso?

Akshat Jiwan Sharma
fonte
3
Porque você não retorna nada a menos que seja uma string. Portanto, o último item retorna undefined. O que você espera retornar se não for uma string? Uma string vazia?
BenM de
2
@BenM se não for uma string, não quero que nada seja retornado. Nem mesmo indefinido.
Akshat Jiwan Sharma
4
Parece que estava usando o método errado para fazer isso. Usarei o filtro conforme sugerido.
Akshat Jiwan Sharma
Você pode querer aceitar uma resposta.
Ikke de
3
jQuery.map é realmente inteligente o suficiente para não incluir valores indefinidos e nulos no array resultante.
Donald Taylor

Respostas:

178

Você não está retornando nada no caso de o item não ser uma string. Nesse caso, a função retorna indefinido, o que você está vendo no resultado.

A função de mapa é usada para mapear um valor para outro, mas parece que você realmente deseja filtrar a matriz, para a qual uma função de mapa não é adequada.

O que você realmente quer é uma função de filtro . Leva uma função que retorna verdadeiro ou falso com base em se você deseja ou não o item na matriz resultante.

var arr = ['a','b',1];
var results = arr.filter(function(item){
    return typeof item ==='string';  
});
Ikke
fonte
2
Ahh ... eu não sabia que existia uma função de filtro.Obrigado.
Akshat Jiwan Sharma
Isso faz bastante sentido. Eu não estava .mapeando, estava .filtrando ... Como você sabia ?! Oo Obrigado ^. ^
DigitalDesignDj
bastante lógico Obrigado @Ikke
Malik Khalil
Economizei meu esforço para procurar uma resposta. Obrigado.
Sophie Zhang,
21

O filtro funciona para este caso específico em que os itens não são modificados. Mas em muitos casos, ao usar o mapa, você deseja fazer algumas modificações nos itens passados.

se essa for sua intenção, você pode usar reduzir :

var arr = ['a','b',1];
var results = arr.reduce((results, item) => {
    if (typeof item === 'string') results.push(modify(item)) // modify is a fictitious function that would apply some change to the items in the array
    return results
}, [])
Nicola Pedretti
fonte
1
Obrigado - mapresulta em matrizes com undefined. filterapenas retorna o item ou não. isso é perfeito
Zach Smith
15

Uma vez que ES6 filtersuporta notação de seta pontiaguda (como LINQ):

Portanto, pode ser resumido a seguir uma linha.

['a','b',1].filter(item => typeof item ==='string');
Matas Vaitkevicius
fonte
10

Minha solução seria usar o filtro após o mapa.

Isso deve suportar todos os tipos de dados JS.

exemplo:

const notUndefined = anyValue => typeof anyValue !== 'undefined'    
const noUndefinedList = someList
          .map(// mapping condition)
          .filter(notUndefined); // by doing this, 
                      //you can ensure what's returned is not undefined
Jojo Narte
fonte
8

Você só retorna um valor se o elemento atual for um string. Talvez atribuir uma string vazia seja suficiente:

var arr = ['a','b',1];
var results = arr.map(function(item){
    return (typeof item ==='string') ? item : '';  
});

Claro, se você quiser filtrar quaisquer elementos que não sejam string, você não deve usar map(). Em vez disso, você deve tentar usar a filter()função.

BenM
fonte
3
Isso retorna uma string vazia se houver um número
Prasath K de
5
var arr = ['a','b',1];
 var results = arr.filter(function(item){
                if(typeof item ==='string'){return item;}  
               });
Prasath K
fonte
2

Você pode implementar como uma lógica abaixo. Suponha que você queira uma matriz de valores.

let test = [ {name:'test',lastname:'kumar',age:30},
             {name:'test',lastname:'kumar',age:30},
             {name:'test3',lastname:'kumar',age:47},
             {name:'test',lastname:'kumar',age:28},
             {name:'test4',lastname:'kumar',age:30},
             {name:'test',lastname:'kumar',age:29}]

let result1 = test.map(element => 
              { 
                 if (element.age === 30) 
                 {
                    return element.lastname;
                 }
              }).filter(notUndefined => notUndefined !== undefined);

output : ['kumar','kumar','kumar']
mkumar
fonte