¿Por qué la función de mapa de JavaScript devuelve undefined?

115

Mi código

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

Esto da los siguientes resultados

["a","b",undefined]

No quiero indefinido en la matriz de resultados, ¿cómo puedo hacerlo?

Akshat Jiwan Sharma
fuente
3
Porque no devuelve nada a menos que sea una cadena. Por tanto, vuelve el último artículo undefined. ¿Qué esperas devolver si no es una cadena? ¿Una cuerda vacía?
BenM
2
@BenM si no es una cadena, no quiero que se devuelva nada, ni siquiera indefinido.
Akshat Jiwan Sharma
4
Parece que estaba usando el método incorrecto para hacer esto. Usaré el filtro como se sugiere.
Akshat Jiwan Sharma
Es posible que desee aceptar una respuesta.
Ikke
3
jQuery.map es lo suficientemente inteligente como para no incluir valores nulos y no definidos en la matriz resultante.
Donald Taylor

Respuestas:

180

No devuelve nada en el caso de que el artículo no sea una cadena. En ese caso, la función devuelve undefined, lo que está viendo en el resultado.

La función de mapa se usa para asignar un valor a otro, pero parece que realmente desea filtrar la matriz, para lo cual una función de mapa no es adecuada.

Lo que realmente desea es una función de filtro . Se necesita una función que devuelva verdadero o falso en función de si desea o no el elemento en la matriz resultante.

var arr = ['a','b',1];
var results = arr.filter(function(item){
    return typeof item ==='string';  
});
Ikke
fuente
2
Ahh ... No sabía que había una función de filtro. Gracias.
Akshat Jiwan Sharma
Esto tiene bastante sentido. No estaba .mapeando. Estaba. Filtrando ... ¡¿Cómo lo supiste ?! Oo Gracias ^. ^
DigitalDesignDj
bastante lógico Gracias @Ikke
Malik Khalil
Ahorré mi esfuerzo por buscar una respuesta. Gracias.
Sophie Zhang
22

El filtro funciona para este caso específico donde los elementos no se modifican. Pero en muchos casos, cuando usa el mapa, desea realizar alguna modificación en los elementos pasados.

si esa es su intención, puede usar reduce :

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
fuente
1
Gracias - mapresultados en matrices con undefined. filterSolo devuelve el artículo o no. esto es perfecto
Zach Smith
15

Dado que ES6 filteradmite la notación de flechas puntiagudas (como LINQ):

Por lo tanto, puede reducirse a seguir una sola línea.

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

Mi solución sería usar un filtro después del mapa.

Esto debería admitir todos los tipos de datos JS.

ejemplo:

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
fuente
8

Solo devuelve un valor si el elemento actual es un string. Quizás asignar una cadena vacía de lo contrario será suficiente:

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

Por supuesto, si desea filtrar cualquier elemento que no sea una cadena, no debe usar map(). Más bien, debería considerar el uso de la filter()función.

BenM
fuente
3
Esto devuelve una cadena vacía si existe un número
Prasath K
5
var arr = ['a','b',1];
 var results = arr.filter(function(item){
                if(typeof item ==='string'){return item;}  
               });
Prasath K
fuente
3

Puede implementar como una lógica siguiente. Suponga que quiere una 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
fuente