同时映射和过滤数组

2020/10/25 16:02 · javascript ·  · 0评论

我有一个要迭代的对象数组,以生成一个新的过滤后的数组。但是,我还需要根据参数从新数组中滤除一些对象。我正在尝试:

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)

reduceES6花式扩展语法的一行在这里!

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()功能组合了mapfilter功能,那就太好它会像过滤器一样工作,除了返回true或false,而是返回任何对象或null / undefined。

我通过以下几点优化了答案:

  1. 改写if (cond) { stmt; }cond && stmt;
  2. 使用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);

我由您决定要采用哪种解决方案。

使用Array.prototy.filter本身

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'];
本文地址:http://javascript.askforanswer.com/tongshiyingsheheguolvshuzu.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!