Last active
June 30, 2021 09:31
-
-
Save alinnert/614da8ebdefa653e006a053a97196f9f to your computer and use it in GitHub Desktop.
A function that flattens a tree structure while preserving nesting information
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { map, flatMapDeep, add, flow } = require('lodash/fp') | |
const data = [ | |
{ | |
id: 1, | |
type: 'group', | |
name: 'Colors', | |
items: [ | |
{ id: 2, type: 'item', name: 'Red' }, | |
{ id: 3, type: 'item', name: 'Purple' }, | |
{ id: 4, type: 'item', name: 'Black' } | |
] | |
}, | |
{ | |
id: 5, | |
type: 'group', | |
name: 'Food', | |
items: [ | |
{ id: 6, type: 'item', name: 'Cheese' }, | |
{ id: 7, type: 'item', name: 'Potatoes' }, | |
{ id: 10, | |
type: 'group', | |
name: 'Sandwich', | |
items: [ | |
{ id: 11, type: 'item', name: 'Bread' }, | |
{ id: 12, type: 'item', name: 'Cheese' }, | |
{ id: 13, type: 'item', name: 'Salami' } | |
] } | |
] | |
}, | |
{ id: 8, type: 'item', name: 'Kitten' }, | |
{ | |
id: 14, | |
type: 'group', | |
name: 'Matryoshka A', | |
items: [ | |
{ | |
id: 15, | |
type: 'group', | |
name: 'Matryoshka B', | |
items: [ | |
{ | |
id: 16, | |
type: 'group', | |
name: 'Matryoshka C', | |
items: [ | |
{ | |
id: 17, | |
type: 'group', | |
name: 'Matryoshka D', | |
items: [ | |
{ | |
id: 18, | |
type: 'item', | |
name: 'Secret Treasure' | |
} | |
] | |
} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ id: 9, type: 'item', name: 'Rainbow' }, | |
{ | |
id: 19, | |
type: 'group', | |
name: 'Box', | |
items: [ | |
{ | |
id: 20, | |
type: 'group', | |
name: 'Box in a box (which is empty)', | |
items: [] | |
} | |
] | |
} | |
] | |
const increment = add(1) | |
const levelizeIterator = childrenProperty => levelProperty => function iterateLevel (level = 0) { | |
return item => { | |
item[levelProperty] = level | |
if (item.hasOwnProperty(childrenProperty)) { | |
const step = flow(increment, iterateLevel, flatMapDeep) | |
const nextLevel = step(level) | |
const children = nextLevel(item[childrenProperty]) | |
delete item[childrenProperty] | |
return [item, children] | |
} | |
return item | |
} | |
} | |
// The children of a node are stored in a property named `items` | |
// The level information will be stored in a property named `level` | |
const itemsLevelizer = levelizeIterator('items')('level') | |
// The `level` property is mainly used interlally. You can set it to whatever you need. | |
// It defaults to 0 | |
const rootItemsLevelizer = itemsLevelizer() | |
const levelizeTree = flatMapDeep(rootItemsLevelizer) | |
const dataFlat = levelizeTree(data) | |
const logJSON = flow(JSON.stringify, console.log) | |
logJSON(dataFlat) | |
const stringifyItem = item => `${' '.repeat(item.level)}[${item.id}] ${item.name} ${item.type === 'group' ? '(+)' : ''}` | |
const logItem = flow(stringifyItem, console.log) | |
const logItems = map(logItem) | |
logItems(dataFlat) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment