Сопоставьте и отфильтруйте массив одновременно
У меня есть массив объектов, которые я хочу перебрать для создания нового фильтрованного массива. Но также, мне нужно отфильтровать некоторые из объектов из нового массива в зависимости от параметра. Я пробую это:
function renderOptions(options) {
return options.map(function (option) {
if (!option.assigned) {
return (someNewObject);
}
});
}
Это хороший подход? Есть ли лучший метод? Я открыт для использования любой библиотеки, такой как lodash.
Ответы
Ответ 1
Вы должны использовать Array.reduce
для этого.
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = options.reduce(function(filtered, option) {
if (option.assigned) {
var someNewValue = { name: option.name, newProperty: 'Foo' }
filtered.push(someNewValue);
}
return filtered;
}, []);
document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1>
<pre id="output"> </pre>
Ответ 2
Используйте уменьшить, Люк!
function renderOptions(options) {
return options.reduce(function (res, option) {
if (!option.assigned) {
res.push(someNewObject);
}
return res;
}, []);
}
Ответ 3
С ES6 вы можете сделать это очень коротко:
options.filter(opt => !opt.assigned).map(opt => someNewObject)
Ответ 4
Array.prototype.flatMap является еще одним вариантом.
options.flatMap(o => o.assigned ? o.name : []);
Со страницы MDN, указанной выше:
flatMap
можно использовать как способ добавления и удаления элементов (изменения количества элементов) во время карты. Другими словами, он позволяет сопоставить множество элементов множеству элементов (обрабатывая каждый элемент ввода отдельно), а не всегда один к одному. В этом смысле он работает как противоположность фильтра. Просто верните массив из 1 элемента, чтобы сохранить элемент, массив из нескольких элементов, чтобы добавить элементы, или массив из 0 элементов, чтобы удалить элемент.
Ответ 5
Одна линия reduce
с ES6 фантазии распространение синтаксис здесь!
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
const filtered = options
.reduce((result, {name, assigned}) => [...result, ...assigned ? [name] : []], []);
console.log(filtered);
Ответ 6
Используйте Array.prototy.filter
function renderOptions(options) {
return options.filter(function(option){
return !option.assigned;
}).map(function (option) {
return (someNewObject);
});
}
Ответ 7
Используя сокращение, вы можете сделать это в одной функции Array.prototype. Это позволит получить все четные числа из массива.
var arr = [1,2,3,4,5,6,7,8];
var brr = arr.reduce(function(c,n){
if(n%2!=0){
return c;
}
c.push(n);
return c;
},[]);
document.getElementById('mypre').innerHTML = brr.toString();
<h1>Get all even numbers</h1>
<pre id="mypre"> </pre>
Ответ 8
В какой-то момент не проще (или просто так) использовать forEach
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = []
options.forEach(function(option) {
if (option.assigned) {
var someNewValue = { name: option.name, newProperty: 'Foo' }
reduced.push(someNewValue);
}
});
document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1>
<pre id="output"> </pre>
Ответ 9
Я оптимизировал ответы со следующими моментами:
- Переписывание
if (cond) { stmt; }
как cond && stmt;
- Использовать ES6 Функции стрелок
Я представлю два решения, используя forEach, другой - reduce:
Решение 1: Использование forEach
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = []
options.forEach(o => {
o.assigned && reduced.push( { name: o.name, newProperty: 'Foo' } );
} );
console.log(reduced);
Ответ 10
Я бы сделал комментарий, но у меня нет необходимой репутации. Небольшое улучшение для Максима Кузьмина, иначе очень хороший ответ, чтобы сделать его более эффективным:
const options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
const filtered = options
.reduce((result, { name, assigned }) => assigned ? result.concat(name) : result, []);
console.log(filtered);