繁体   English   中英

如何使用ramda将平面列表转换为分层列表?

[英]How to turn flat list into hierarchical one using ramda?

喜欢有问题。 我想将以下列表转换为带有子字段的分层列表。 “ parentId”可以保留。 为了清楚起见,我只是删除了它。 目标是使用具有不变行为的ramda。

const x = [
  {
    id: 1,
    parentId: null,
    name: 'Top 1'
  },
  {
    id: 2,
    parentId: 1,
    name: 'Middle'
  },
  {
    id: 3,
    parentId: 2,
    name: 'Leaf'
  },
  {
    id: 4,
    parentId: null,
    name: 'Top 2'
  },
];

进入这个:

const result = [
    {
        id: 1,
        name: 'Top 1',
        children: [
            {
                id: 2,
                name: 'Middle',
                children: [
                    {
                        id: 3,
                        name: 'Leaf',
                        children: []
                    }
                ]
            }
        ]
    },
    {
        id: 4,
        name: 'Top 2',
        children: []
    }
];

正如我在Gitter中回答的那样,这似乎可以做到:

const makeTree = items => {
  const hierarchy = reduce(
    (index, item) => item.parentId in index 
      ? assoc(item.id, [], assoc(item.parentId, append(item.id, index[item.parentId]), index))
      : assoc(item.id, [], index)
    , {}, 
    items
  ) //=> E.g. {"1":[2],"2":[3],"3":[],"4":[]} 
  const index = map(head, groupBy(prop('id'), items)) //=> E.g. {"!": <item1>, "2": <item2>, ...}
  const makeNode = id => dissoc('parentId', assoc('children',  map(makeNode, hierarchy[id]), index[id]))

  return map(makeNode, pluck('id', filter(item => item.parentId == null, items)))
}

它确实涉及对数据的多次传递,并且在此处使用groupBy似乎有点groupBy ,但我认为这是合理的。

而且那些嵌套的assoc也不漂亮。 我可能会重构为compose / pipe

您可以在Ramda REPL上看到这一点。

在纯Ramda /无点/功能样式中,我将执行以下操作:

const overChildren = over(lensProp('children'))
const findChildren = completeList => parent => filter(child => child.parentId === parent.id, completeList)

const assocChildren = completeList => map(pipe(
  parent => assoc('children', findChildren(completeList)(parent), parent),
  parent => overChildren(assocChildren(completeList), parent)
))

const removeParentIds = map(pipe(
  dissoc('parentId'),
  overChildren(x => removeParentIds(x))
))

const isTop = compose(isNil, prop('parentId'))
const keepOnlyTop = filter(isTop)

const hierarchize = completeList => pipe(
  assocChildren(completeList),
  keepOnlyTop,
  removeParentIds
)(completeList)

hierarchize(list)

在这里尝试

注意:我专注于可读性和可维护性,而不是性能。

暂无
暂无

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

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