Я бы начал с простой функции traverse
-
const traverse = function* (t = {})
{ if (t == null) return
for (const [ name, children ] of Object.entries(t))
{ yield name
yield* traverse(children)
}
}
console.log(Array.from(traverse(family)))
// [ "Beverly Marquez"
// , "Nina Rhone"
// , "William Rhodes"
// , "Paul Nell"
// , "Sir Paddington the Fourth, of the county Wilstonshire"
// ]
Это отделяет обход вашего дерева от операции, которую вы хотите выполнить над значениями дерева.Теперь мы реализуем простую longestName
функцию -
const longestName = (t = {}) =>
{ let r = ""
for (const name of traverse(t))
if (name.length > r.length)
r = name
return r
}
console.log(longestName(family))
// Sir Paddington the Fourth, of the county Wilstonshire
Как видите, написание longestName
теперь легко, поскольку нам не нужно одновременно заниматься логикой обхода.
Разверните фрагмент ниже, чтобы проверить результаты в своем собственном браузере -
let family = {
'Beverly Marquez': {
'Nina Rhone': {
'William Rhodes': null,
'Paul Nell': null,
'Sir Paddington the Fourth, of the county Wilstonshire': null
}
}
}
const traverse = function* (t = {})
{ if (t == null) return
for (const [ name, children ] of Object.entries(t))
{ yield name
yield* traverse(children)
}
}
const longestName = (t = {}) =>
{ let r = ""
for (const name of traverse(t))
if (name.length > r.length)
r = name
return r
}
console.log(longestName(family))
// Sir Paddington the Fourth, of the county Wilstonshire
console.log(Array.from(traverse(family)))
// [ "Beverly Marquez"
// , "Nina Rhone"
// , "William Rhodes"
// , "Paul Nell"
// , "Sir Paddington the Fourth, of the county Wilstonshire"
// ]
Если бы в дереве были другие данные, вы можете увидеть, как было бы легко написать другие функции, используя traverse
-
const myTree =
{ name: "Alice"
, gender: "F"
, children:
[ { name: "Bob"
, gender: "M"
, children:
[ { name: "Charles"
, gender: "M"
}
]
}
]
}
const traverse = function* ({ children = [], ...t })
{ yield t
for (const child of children)
yield* traverse(child)
}
const filter = function* (test, t = {})
{ for (const leaf of traverse(t))
if (test(leaf))
yield leaf
}
const byGender = (q = "", t = {}) =>
filter(node => node.gender === q, t)
console.log(Array.from(byGender("M", myTree)))
// [ { name: "Bob", gender: "M" }, { name: "Charles", gender: "M" } ]
console.log(Array.from(byGender("F", myTree)))
// [ { name: "Alice", gender: "F" } ]