使用rxjs扁平的对象嵌套阵列

发布于 2025-01-20 23:13:21 字数 1467 浏览 2 评论 0原文

我们的数据结构是一个嵌套的数组,

interface dtModel {
  id: number;
  permission: number;
  childs: dtModel[];
}

const data: dtModel[] = [
  {
    id: 1,
    permission: 2,
    childs: [
      {
        id: 2,
        permission: 1,
        childs: [
          {
            id: 3,
            permission: 3,
            childs: [],
          },
        ],
      },
    ],
  },
  {
    id: 4,
    permission: 1,
    childs: [
      {
        id: 5,
        permission: 2,
        childs: [
          {
            id: 6,
            permission: 3,
            childs: [
              {
                id: 7,
                permission: 1,
                childs: [],
              },
            ],
          },
        ],
      },
    ],
  },
];

我在RXJ的帮助下尝试的对象创建了一个扁平的阵列,但我尚未成功,但

[
  {id:1,permission:2},
  {id:2,permission:1},
  {id:3,permission:3},
  {id:4,permission:1},
  {id:5,permission:2},
  {id:6,permission:3},
  {id:7,permission:1}
]

我尝试在“降低”的帮助下做到这一点,但因为我的孩子的属性并不总是拥有与这种方法相同的长度。

of(data)
  .pipe(
    map((items: dtModel[]) => {
      return items.reduce((res, curr) => {
        res.push({ id: curr.id, permission: curr.permission });
        return res;
      }, []);
    })
  )
  .subscribe(console.log);

stackblitz

our data structure is a nested array with objects

interface dtModel {
  id: number;
  permission: number;
  childs: dtModel[];
}

const data: dtModel[] = [
  {
    id: 1,
    permission: 2,
    childs: [
      {
        id: 2,
        permission: 1,
        childs: [
          {
            id: 3,
            permission: 3,
            childs: [],
          },
        ],
      },
    ],
  },
  {
    id: 4,
    permission: 1,
    childs: [
      {
        id: 5,
        permission: 2,
        childs: [
          {
            id: 6,
            permission: 3,
            childs: [
              {
                id: 7,
                permission: 1,
                childs: [],
              },
            ],
          },
        ],
      },
    ],
  },
];

I tried with help of RxJs to create a flattened array like this which is I'm not succeeded yet

[
  {id:1,permission:2},
  {id:2,permission:1},
  {id:3,permission:3},
  {id:4,permission:1},
  {id:5,permission:2},
  {id:6,permission:3},
  {id:7,permission:1}
]

I tried to do that with help of 'reduce' but because my childs' property does not always have the same length I couldn't do that with this approach.

of(data)
  .pipe(
    map((items: dtModel[]) => {
      return items.reduce((res, curr) => {
        res.push({ id: curr.id, permission: curr.permission });
        return res;
      }, []);
    })
  )
  .subscribe(console.log);

StackBlitz

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

丢了幸福的猪 2025-01-27 23:13:21

需要进行递归

const source = [
  {
    id: 1,
    permission: 2,
    childs: [
      {
        id: 2,
        permission: 1,
        childs: [
          {
            id: 3,
            permission: 3,
            childs: [],
          },
        ],
      },
    ],
  },
  {
    id: 4,
    permission: 1,
    childs: [
      {
        id: 5,
        permission: 2,
        childs: [
          {
            id: 6,
            permission: 3,
            childs: [
              {
                id: 7,
                permission: 1,
                childs: [],
              },
            ],
          },
        ],
      },
    ],
  },
];

const result  = [];

const getAllItemsPerChildren = (item) => {
  result.push({ id: item.id, permission: item.permission });
  if (item.childs) {
    return item.childs.map((i) => getAllItemsPerChildren(i));
  }
};

source.forEach((i) => getAllItemsPerChildren(i));

console.log(result)

rxjs解决方案

demo: htttps://stackblitz.com /Edit/typescript -dlva1z?file= index.ts


const source$ = of({
  data: [],
  last: false,
  check: source,
}).pipe(
  expand((data) =>
    data.last
      ? EMPTY
      : of(data.check).pipe(
          map((currentItem) => {
            const childs = (currentItem as any).flatMap((i) => i?.childs || []);
            return {
              data: currentItem.map((i) => ({
                id: i.id,
                permissions: i.permission,
              })),
              last: !childs?.length,
              check: childs,
            };
          })
        )
  ),
  reduce((acc, items) => [...acc, ...(items as any).data], [])
);
source$.subscribe((data) => console.log('result ', data));

说明:

  • 使用Expand> Expand操作员的主要思想 - 它允许我们创建递归。
  • 要停止递归需要返回
  • ({data:[],last:false,check:source}) - 这是我们的商店
  • data被分配以保留分析的项目 - 将用于减少操作员 - 对整个数据cont
  • 一个从展开等于一个emit
  • last 允许控制恢复,我们正在检查所有项目是否均被解析
  • 检查 - 解析的元素,将Intial值设置为整个数据

need to make recursion

const source = [
  {
    id: 1,
    permission: 2,
    childs: [
      {
        id: 2,
        permission: 1,
        childs: [
          {
            id: 3,
            permission: 3,
            childs: [],
          },
        ],
      },
    ],
  },
  {
    id: 4,
    permission: 1,
    childs: [
      {
        id: 5,
        permission: 2,
        childs: [
          {
            id: 6,
            permission: 3,
            childs: [
              {
                id: 7,
                permission: 1,
                childs: [],
              },
            ],
          },
        ],
      },
    ],
  },
];

const result  = [];

const getAllItemsPerChildren = (item) => {
  result.push({ id: item.id, permission: item.permission });
  if (item.childs) {
    return item.childs.map((i) => getAllItemsPerChildren(i));
  }
};

source.forEach((i) => getAllItemsPerChildren(i));

console.log(result)

RXJS SOLUTION

demo: https://stackblitz.com/edit/typescript-dlva1z?file=index.ts


const source$ = of({
  data: [],
  last: false,
  check: source,
}).pipe(
  expand((data) =>
    data.last
      ? EMPTY
      : of(data.check).pipe(
          map((currentItem) => {
            const childs = (currentItem as any).flatMap((i) => i?.childs || []);
            return {
              data: currentItem.map((i) => ({
                id: i.id,
                permissions: i.permission,
              })),
              last: !childs?.length,
              check: childs,
            };
          })
        )
  ),
  reduce((acc, items) => [...acc, ...(items as any).data], [])
);
source$.subscribe((data) => console.log('result ', data));

Explanation:

  • The main idea to use expand operator - it allow us to create recursion.
  • To stop recursion need to return EMPTY
  • of({data: [],last: false, check: source}) - it is our store
  • data is assigned to keep parsed item - that will be used in reduce operator - to concat the whole data
  • one return from expand equal to one emit
  • last allows to control recusrion, we are checking if all items is parsed
  • check - element to parse, intial value set to your entire data
沫尐诺 2025-01-27 23:13:21

简化的 expand 版本,只需要确保发出每个项目并在最后使用 map

工作示例进行一些清理:https://codesandbox.io/s/rxjs-playground-forked-vr0l6s?file=/src/index.js

from(data)
  .pipe(
    expand((obj) => {
      return obj.childs && obj.childs.length
        ? from(obj.childs)
        : EMPTY;
    }),
    map(obj=>({ id: obj.id, permission: obj.permission })),
    toArray()
  )
  .subscribe(console.log);

非常好的文章解释了expand用法https://ncjamieson.com/understand-expand/

A simplified expand version, just need to ensure every item is emitted and do some clean up at the end with map

working example: https://codesandbox.io/s/rxjs-playground-forked-vr0l6s?file=/src/index.js

from(data)
  .pipe(
    expand((obj) => {
      return obj.childs && obj.childs.length
        ? from(obj.childs)
        : EMPTY;
    }),
    map(obj=>({ id: obj.id, permission: obj.permission })),
    toArray()
  )
  .subscribe(console.log);

very good article explains expand usage https://ncjamieson.com/understanding-expand/

情定在深秋 2025-01-27 23:13:21

您需要进行树(=您的数据结构)遍历,并且对于每个节点,您必须将 {id://some id,permission://somepermission} 推送到结果数组上。

你不需要 rxjs。

You need to do a tree (= your data structure) traversal and for every node you have to push {id://some id,permission://some permission} on a result array.

You don't need rxjs for that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文