繁体   English   中英

如何在 JavaScript 中的 flatMap 数组方法中获取累加器(flatmap vs reduce)?

[英]How to get accumulator in flatMap array methode in JavaScript(flatmap vs reduce)?

有一个初始数组需要同时映射和过滤:

let data = [
        {
            "id": 1,
            "parentId": null,
            "dxId": "1_id",
            "dxParentId": null,
            "defName": "group1"
        },
        {
            "id": 12,
            "parentId": null,
            "dxId": "12_id",
            "dxParentId": null,
            "defName": "группа3"
        },
        {
            "id": 8,
            "parentId": 1,
            "dxId": "1_id/13",
            "dxParentId": "1_id",
            "defName": "group4"
        },
        {
            "id": 5,
            "parentId": 1,
            "dxId": "1_id/20",
            "dxParentId": "1_id",
            "defName": "user1"
        },
        {
            "id": 5,
            "parentId": 1,
            "dxId": "1_id/20",
            "dxParentId": "12_id",
            "defName": "user1"
        },
    ];

我通过 parentide 属性的存在进行过滤,并收集结果字符串数组(不是初始对象数组)。

最初我是通过reduce方法做到的:

resultArr = data.reduce((filtered, obj) => {
                                if(  obj.dx_parentId !== null) {
                                    if(!(filtered.includes(obj.dxParentId)))  {
                                        filtered.push(obj.dxParentId);
                                    }
                                }
                                return filtered;
                            }, []);
 console.log(resultArr , 'result'); // ['1_id', '12_id'] 'result'

然后我自己发现这可以用 flatMap 数组方法来完成

resultArr =  data.flatMap((obj) =>  obj.dxParentId !== null ? [obj.dxParentId] : []);
console.log(resultArr , 'result'); //['1_id', '1_id', '12_id'] 'result'

如果您注意到在减少的情况下我使用过滤(累加数组) ,我会使用包含进行额外检查,我会得到我需要的结果。

问题是如何通过 flatMap 做同样的事情? 是否可以在每次迭代时访问累积结果?

另外:有人可以告诉我在优化方面用什么更好地解决这种情况? mb forEach? 提前致谢

您无法访问在flatMap中构建的数组。 在映射以及带扁平化的映射中,回调应该返回一个仅取决于特定项目的值。

对于这样的命令式算法,您可能根本不想使用reduce

const resultArr = [];
for (const obj of data) {
    if (obj.dxParentId !== null) {
        if (!resultArr.includes(obj.dxParentId)) {
            filtered.push(obj.dxParentId);
        }
    }
}
console.log(resultArr, 'result');

但是,要从数组中获取唯一值,有一种更好(更简单、更有效)的方法:

const resultArr = Array.from(new Set(data.map(obj => obj.dxParentId).filter(id => id !== null)));
console.log(resultArr, 'result');

因此,虽然您无法在构建阵列平面图时查看它正在构建,但您可以在平面图之外创建一个 object 并使用它来跟踪您添加或未添加的 id。

const seen = {};
const resultArr = data.flatMap((obj) => {
  const id = obj.dxParentId;
  if (id in seen) return [];
  if (id !== null) {
    seen[id] = true;
    return [id];
  }
  return [];
});
console.log(resultArr, "result"); //['1_id', '1_id', '12_id'] 'result'

就时间和空间复杂性而言,此解决方案要快得多,但占用更多空间(在大多数情况下这是一个很好的权衡)。

Array.include() 遍历整个数组,时间复杂度为 O(n)。 object 中的关键具有恒定的时间复杂度,但构建 object 是 O(n) 空间。

在我看来,最好的解决方案是将 object 的即时查找与 reduce 的范围相结合。

const resultArr = data.reduce(
  (acc, obj) => {
    const id = obj.dxParentId;
    const { seen, filtered } = acc;
    if (id in seen) return acc;
    if (id !== null) {
      seen[id] = true;
      filtered.push(id);
    }
    return acc;
  },
  { seen: {}, filtered: [] }
).filtered;
console.log(resultArr, "result"); // ['1_id', '12_id'] 'result'

此解决方案具有与平面图相同的时间和空间复杂性,但看到的 object 在 reduce 方法完成后就可以进行垃圾收集,因此这些潜在的空间问题并不那么重要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM