[英]How to turn flat list into hierarchical one using ramda?
Like in question. 喜欢有问题。 I would like to turn the following list into hierarchical list with children fields. 我想将以下列表转换为带有子字段的分层列表。 'parentId' can stay. “ parentId”可以保留。 I just removed it for clarity. 为了清楚起见,我只是删除了它。 The goal is to use ramda with its immutable behavior. 目标是使用具有不变行为的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'
},
];
into this one: 进入这个:
const result = [
{
id: 1,
name: 'Top 1',
children: [
{
id: 2,
name: 'Middle',
children: [
{
id: 3,
name: 'Leaf',
children: []
}
]
}
]
},
{
id: 4,
name: 'Top 2',
children: []
}
];
As I answered in Gitter , this seems to do it: 正如我在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)))
}
It does involve several passes through the data, and the use of groupBy
here seems a bit hacky, but I think it's reasonable. 它确实涉及对数据的多次传递,并且在此处使用groupBy
似乎有点groupBy
,但我认为这是合理的。
Also those nested assoc
s aren't pretty. 而且那些嵌套的assoc
也不漂亮。 I might refactor into compose
/ pipe
. 我可能会重构为compose
/ pipe
。
You can see this in action on the Ramda REPL . 您可以在Ramda REPL上看到这一点。
In a pure Ramda / point-free / functional style, I would do the following: 在纯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)
Note: I've focused on the readability and maintainability, not on performance. 注意:我专注于可读性和可维护性,而不是性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.