我有一个对象数组,我想迭代生成一个新的过滤数组。但是,我还需要根据参数从新数组中过滤掉一些对象。我试过这个:
function renderOptions(options) {
return options.map(function (option) {
if (!option.assigned) {
return (someNewObject);
}
});
}
这是一个好方法吗?有更好的方法吗?我打开使用任何库,例如lodash。
答案 0 :(得分:118)
您应该使用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>
更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
答案 1 :(得分:38)
使用reduce,Luke!
function renderOptions(options) {
return options.reduce(function (res, option) {
if (!option.assigned) {
res.push(someNewObject);
}
return res;
}, []);
}
答案 2 :(得分:14)
使用ES6,你可以做得很短:
options.filter(opt => !opt.assigned).map(opt => someNewObject)
答案 3 :(得分:5)
ES6花式spread syntax的一行reduce
就在这里!
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);
答案 4 :(得分:3)
function renderOptions(options) {
return options.filter(function(option){
return !option.assigned;
}).map(function (option) {
return (someNewObject);
});
}
答案 5 :(得分:3)
Array.prototype.flatMap是另一种选择。
const options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
options.flatMap(o => o.assigned ? o.name : []);
// ['One', 'Three']
从上面链接的MDN页面上:
flatMap
可用作添加和删除项目的方法(修改 地图中的项数)。换句话说,它允许您映射 许多项目到许多项目(通过分别处理每个输入项目), 而不是总是一对一的。从这个意义上讲,它就像 过滤器的对面。只需返回一个1元素数组即可保留该项目, 一个多元素数组以添加项目,或一个0元素数组以删除项目 该项目。
答案 6 :(得分:1)
使用reduce,您可以在一个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>
您可以使用相同的方法并将其概括为您的对象,例如:
var arr = options.reduce(function(c,n){
if(somecondition){return c;}
c.push(n); return c;
},[]);
arr
现在将包含已过滤的对象。
答案 7 :(得分:1)
在某些时候,使用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);
&#13;
<h1>Only assigned options</h1>
<pre id="output"> </pre>
&#13;
但是,如果malter()
或fap()
函数结合了map
和filter
函数,那就太好了。它会像过滤器一样工作,除了不返回true或false,它将返回任何对象或null / undefined。
答案 8 :(得分:1)
我用以下几点优化了答案:
if (cond) { stmt; }
重写为cond && stmt;
我将提供两个解决方案,一个使用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);
&#13;
解决方案2:使用reduce
var options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
var reduced = options.reduce((a, o) => {
o.assigned && a.push( { name: o.name, newProperty: 'Foo' } );
return a;
}, [ ] );
console.log(reduced);
&#13;
我可以决定选择哪种解决方案。
答案 9 :(得分:1)
我要发表评论,但我没有所需的声誉。对Maxim Kuzmin的其他很好的答案进行了小幅改进,使其更加有效:
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);
说明
我们不会在每次迭代中一遍又一遍地散布整个结果,而是仅在实际有要插入的值时才追加到数组。
答案 10 :(得分:0)
直接使用.reduce
可能很难读懂,所以我建议创建一个为您生成减速器的函数:
function mapfilter(mapper) {
return (acc, val) => {
const mapped = mapper(val);
if (mapped !== false)
acc.push(mapped);
return acc;
};
}
像这样使用它:
const words = "Map and filter an array #javascript #arrays";
const tags = words.split(' ')
.reduce(mapfilter(word => word.startsWith('#') && word.slice(1)), []);
console.log(tags); // ['javascript', 'arrays'];
答案 11 :(得分:0)
你可以使用带有箭头函数的 Array.reduce
是一行代码
const options = [
{ name: 'One', assigned: true },
{ name: 'Two', assigned: false },
{ name: 'Three', assigned: true },
];
const reduced = options.reduce((result, option) => option.assigned ? result.concat({ name: option.name, newProperty: 'Foo' }) : result, []);
document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1>
<pre id="output"> </pre>