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

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

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


当前回答

从2019年开始,Array.prototype.flatMap是一个不错的选择。

options.flatMap(o => o.assigned ? [o.name] : []);

从MDN页面上方链接:

flatMap可以作为一种添加和删除项目的方法(修改 项目数目)在一个地图。换句话说,它允许您进行映射 多项对多项(通过分别处理每个输入项), 而不是总是一对一。在这个意义上,它就像 filter的反义词。只需返回一个1元素的数组来保存该项, 用于添加项的多元素数组,或用于删除项的0元素数组 的项目。

其他回答

嘿,我刚刚在这个项目上工作,想在MDN文档中分享我基于Array.prototype.flatMap()的解决方案:

const places=[{latitude:40,longitude:1},{latitude:41,longitude:2},{latitude:44,longitude:2},{latitude:NaN,longitude:NaN},{latitude:45,longitude:4},{latitude:48,longitude:3},{latitude:44,longitude:5},{latitude:39,longitude:13},{latitude:40,longitude:8},{latitude:38,longitude:4}]; let items = places?.map((place) => [{ latitude: (place.latitude), longitude: (place.longitude), }, ]); console.log("Items: ", items); //Remove elements with NaN latitude and longitude let newItems = places?.flatMap((o) => Number(o.longitude, o.latitude) ? { lng: Number(o.longitude), lat: Number(o.latitude) } : [] ); console.log("Coordinates after NaN values removed: ", newItems);

使用Array.prototype.filter:

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

用减法,卢克!

function renderOptions(options) {
    return options.reduce(function (res, option) {
        if (!option.assigned) {
            res.push(someNewObject);
        }
        return res;
    }, []);   
}

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

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

如(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)] : []));

直接使用.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'];