Почему функция карты javascript возвращает значение undefined?

116

Мой код

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

Это дает следующие результаты

["a","b",undefined]

Я не хочу, чтобы в массиве результатов содержалось значение undefined, как это сделать?

Акшат Дживан Шарма
источник
3
Потому что вы ничего не возвращаете, кроме строки. Следовательно, возвращается последний элемент undefined. Что вы ожидаете вернуть, если это не строка? Пустая строка?
BenM
2
@BenM, если это не строка, я не хочу ничего возвращать, даже не неопределенного.
Акшат Дживан Шарма
4
Похоже, я использовал неправильный метод для этого. Я буду использовать фильтр, как было предложено.
Акшат Дживан Шарма
Возможно, вы захотите принять ответ.
Ikke
3
jQuery.map на самом деле достаточно умен, чтобы не включать неопределенные и нулевые значения в результирующий массив.
Дональд Тейлор

Ответы:

181

Вы ничего не возвращаете, если элемент не является строкой. В этом случае функция возвращает undefined, что вы видите в результате.

Функция карты используется для сопоставления одного значения с другим, но похоже, что вы действительно хотите отфильтровать массив, для чего функция карты не подходит.

На самом деле вам нужна функция фильтра . Требуется функция, которая возвращает истину или ложь в зависимости от того, нужен ли вам элемент в результирующем массиве или нет.

var arr = ['a','b',1];
var results = arr.filter(function(item){
    return typeof item ==='string';  
});
Икке
источник
2
Ааа ... Не знал, что есть функция фильтра. Спасибо.
Акшат Дживан Шарма
В этом есть некоторый смысл. Я не .map'ing, я .filter'ing ... Откуда вы знаете ?! Оо Спасибо ^. ^
DigitalDesignDj
вполне логично Спасибо @Ikke
Малик Халил
Сэкономил мои усилия на поиск ответа. Спасибо.
Софи Чжан
24

Фильтр работает для этого конкретного случая, когда элементы не изменяются. Но во многих случаях, когда вы используете карту, вы хотите внести некоторые изменения в переданные элементы.

если это ваше намерение, вы можете использовать сокращение :

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
}, [])
Никола Педретти
источник
1
Спасибо - mapрезультаты в массивах с undefined. filterтолько возвращает товар или нет. это идеально
Зак Смит
15

Поскольку ES6 filterподдерживает обозначение остроконечных стрелок (например, LINQ):

Таким образом, это можно свести к следующему однострочному.

['a','b',1].filter(item => typeof item ==='string');
Матас Вайткявичюс
источник
11

Моим решением было бы использовать фильтр после карты.

Это должно поддерживать все типы данных JS.

пример:

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
источник
8

Вы возвращаете значение, только если текущий элемент - это string. Возможно, в противном случае будет достаточно присвоения пустой строки:

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

Конечно, если вы хотите отфильтровать любые нестроковые элементы, вам не следует использовать map(). Скорее вам следует изучить возможность использования filter()функции.

BenM
источник
3
Это возвращает пустую строку, если существует число
Прасат К.
5
var arr = ['a','b',1];
 var results = arr.filter(function(item){
                if(typeof item ==='string'){return item;}  
               });
Прасат К
источник
3

Вы можете реализовать следующую логику. Предположим, вам нужен массив значений.

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']
Мкумар
источник