有问题。我想将以下列表转换为带有子字段的分层列表。 ' 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: []
}
];
答案 0 :(得分:0)
正如我在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
在这里的使用似乎有些苛刻,但我认为这是合理的。
那些嵌套的assoc
也不漂亮。我可能会重构为compose
/ pipe
。
您可以在 Ramda REPL 上看到这一点。
答案 1 :(得分:0)
在纯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)
注意:我专注于可读性和可维护性,而不是性能。