通过过滤对象数组减少对象数组

时间:2020-06-26 11:07:11

标签: javascript arrays include big-o reduce

我的函数以字符串形式发送ID数组,并返回对象数组。它有效,太好了!但我确信,有一个更优雅的解决方案。我在数组上进行迭代,然后foreach在第二个数组上进行迭代,如果找到匹配项,则在第三个数组上进行迭代以检查重复项。

myMethod: state => (argsArray) => {

    const myCampaigns = argsArray.reduce((acc, num) => {
      state.campaigns.forEach(item => {
        if (item.segmentIds.includes(num) && !acc.includes(item)) {
          acc.push(item)
        }
      })
      return acc
    }, [])

    return myCampaigns
  }

1 个答案:

答案 0 :(得分:0)

据我对您的代码的了解,初始值如下:

state = {
  campaigns: [
    {segmentIds:[1,2,3]}, {segmentIds:[4,5,6], ...}
  ]
}
argsArray = [1, 3, 6]

您的代码中有两次迭代,使您的运行时二次方……不理想。

您想要的是避免嵌套迭代。您可以通过创建包含所有segmentId的变量来简化查找的方法。另外,请尝试使用Javascript的Set data type,因为它具有很好的查找时间复杂度。

您的问题的可能解决方案:

// store all your segmentIds before your iteration
// and flatten your array
const segmentIds = state.campaigns
  .reduce((accumulator, campaign) => {
    return campaign.segmentIds.reduce((acc, id) => {
      if (acc.has(id)) return acc;
      acc.add(id);
      return acc;
    }, accumulator);
  }, new Set());
//
const myCampaigns = argsArray.reduce((acc, num) => {
  if (segmentIds.has(num) && !acc.includes(item)) {
    acc.push(item);
  }
  return acc;
}, []);

或者,如果您对两次缩减都不满意,则可以尝试使用Lodash's flatten method

const segmentIds = _.flatten(
  state.campaigns.map(campaign => campaign.segmentIds)
)