我有一个对象数组,我想对其进行迭代以生成一个新的过滤数组。同时,我还需要根据参数从新数组中过滤出一些对象。我试着这样做:

function renderOptions(options) {
    return options.map(function (option) {
        if (!option.assigned) {
            return (someNewObject);
        }
    });   
}

这是个好方法吗?有没有更好的方法?我愿意使用任何库,如lodash。


当前回答

你应该使用Array。减少这个。

Var选项= [ {name: 'One', assigned: true}, {name: 'Two',赋值:false}, {name: 'Three',赋值:true}, ]; Var减少=选项。减少(函数(筛选,选项){ If (option.assigned) { var someenewvalue = {name: option.name, newProperty: 'Foo'} filtered.push (someNewValue); } 返回过滤; },[]); . getelementbyid(“输出”)。innerHTML = JSON.stringify(简化); <h1>仅分配选项</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;
}, []);

其他回答

我把这些伟大的答案隐藏在效用函数中,我想分享它们:

示例:只过滤奇数并增加它

如(1、2、3、4、5)过滤器- >(1、3、5)地图——>(2、4、6)

通常过滤器和映射都是这样

const inputArray = [1, 2, 3, 4, 5];
const filterOddPlusOne = inputArray.filter((item) => item % 2).map((item) => item + 1); // [ 2, 4, 6 ]

使用减少

const filterMap = <TSource, TTarget>(
  items: TSource[],
  filterFn: (item: TSource) => boolean,
  mapFn: (item: TSource) => TTarget
) =>
  items.reduce((acc, cur): TTarget[] => {
    if (filterFn(cur)) return [...acc, mapFn(cur)];
    return acc;
  }, [] as TTarget[]);

使用flatMap

const filterMap = <TSource, TTarget>(
  items: TSource[],
  filterFn: (item: TSource) => boolean,
  mapFn: (item: TSource) => TTarget
) => items.flatMap((item) => (filterFn(item) ? [mapFn(item)] : []));

用法(reduce和flatMap解决方案相同):

const inputArray = [1, 2, 3, 4, 5];
const filterOddPlusOne = filterMap(
  inputArray,
  (item) => item % 2, // Filter only odd numbers
  (item) => item + 1 // Increment each number
); // [ 2, 4, 6 ]

JavaScript版本

上面的代码是TypeScript的,但是问题问的是JavaScript。所以,我已经为你删除了所有的泛型和类型:

const filterMap = (items, filterFn, mapFn) =>
  items.reduce((acc, cur) => {
    if (filterFn(cur)) return [...acc, mapFn(cur)];
    return acc;
  }, []);
const filterMap = (items, filterFn, mapFn) =>
  items.flatMap((item) => (filterFn(item) ? [mapFn(item)] : []));

我用以下几点优化了答案:

重写if (cond) {stmt;}作为cond && stmt; 使用ES6箭头函数

我将给出两个解决方案,一个使用forEach,另一个使用reduce:

解决方案1:使用forEach

该解决方案通过使用forEach遍历每个元素来实现。然后,在forEach循环的主体中,我们有条件作为过滤器,它决定我们是否要向结果数组追加一些内容。

Const选项= [ {name: 'One', assigned: true}, {name: 'Two',赋值:false}, {name: 'Three',赋值:true}, ]; Const reduced = []; 选项。forEach(o => { O.assigned && reduced。push({name: o.name, newProperty: 'Foo'}); }); console.log(减少);

解决方案2:使用reduce

这个解决方案使用array. prototype.reduce而不是forEach来迭代数组。它认识到这样一个事实,即reduce具有内置的初始化式和循环机制。除此之外,该解决方案与forEach解决方案或多或少是相同的,因此,区别在于修饰语法。

Const选项= [ {name: 'One', assigned: true}, {name: 'Two',赋值:false}, {name: 'Three',赋值:true}, ]; Const reduced = options。Reduce ((a, o) => { o.assigned && a.push({name: o.name, newProperty: 'Foo'}); 返回一个; }, []); console.log(减少);

我让你来决定采用哪种解决方案。

在某些情况下,使用forEach不是更容易(或同样容易)吗

Var选项= [ {name: 'One', assigned: true}, {name: 'Two',赋值:false}, {name: 'Three',赋值:true}, ]; Var减小= [] options.forEach(功能(选项){ If (option.assigned) { var someenewvalue = {name: option.name, newProperty: 'Foo'} reduced.push (someNewValue); } }); . getelementbyid(“输出”)。innerHTML = JSON.stringify(简化); <h1>仅分配选项</h1> <pre id="output"> </pre> .

但是,如果有一个malter()或fap()函数组合映射和过滤器函数就更好了。它将像过滤器一样工作,除了返回true或false之外,它将返回任何对象或null/undefined。

在ES6中,你可以做的很短:

选项。过滤器(opt => !opt.assigned)。目录(opt => someNewObject)

直接使用.reduce可能很难阅读,所以我建议创建一个生成reducer的函数:

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'];