我有一个要迭代的对象数组,以生成一个新的过滤后的数组。但是,我还需要根据参数从新数组中滤除一些对象。我正在尝试:
function renderOptions(options) {
return options.map(function (option) {
if (!option.assigned) {
return (someNewObject);
}
});
}
那是个好方法吗?有没有更好的方法?我愿意使用lodash之类的任何库。
您应该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>
另外,减速器可以是一个纯函数,像这样
var reduced = options.reduce(function(result, option) {
if (option.assigned) {
return result.concat({
name: option.name,
newProperty: 'Foo'
});
}
return result;
}, []);
使用减少,卢克!
function renderOptions(options) {
return options.reduce(function (res, option) {
if (!option.assigned) {
res.push(someNewObject);
}
return res;
}, []);
}
自2019年以来,Array.prototype.flatMap是一个不错的选择。
options.flatMap(o => o.assigned ? [o.name] : []);
在上面链接的MDN页面上:
flatMap
可以用作在地图中添加和删除项目(修改项目数)的方法。换句话说,它允许您将许多项目映射到许多项目(通过分别处理每个输入项目),而不是始终一对一。从这个意义上说,它的工作原理与过滤器相反。只需返回一个1元素数组以保留该项目,返回一个多元素数组以添加项目,或返回0元素数组以删除该项目。
使用ES6,您可以做得很短:
options.filter(opt => !opt.assigned).map(opt => someNewObject)
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);
我会发表评论,但我没有所需的声誉。对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);
说明
我们不会在每次迭代中一遍又一遍地散布整个结果,而是仅在实际存在要插入的值时才追加到数组。
在某个时候,使用它难吗(或同样容易) 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>
但是,如果有一个malter()
或fap()
功能组合了map
和filter
功能,那就太好了。它会像过滤器一样工作,除了返回true或false,而是返回任何对象或null / undefined。
我通过以下几点优化了答案:
- 改写
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);
解决方案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);
我由您决定要采用哪种解决方案。
function renderOptions(options) {
return options.filter(function(option){
return !option.assigned;
}).map(function (option) {
return (someNewObject);
});
}
使用reduce,可以在一个Array.prototype函数中执行此操作。这将从数组中获取所有偶数。
var arr = [1,2,3,4,5,6,7,8];
var brr = arr.reduce((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
现在将包含过滤的对象。
直接使用.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'];
文章标签:arrays , javascript
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!