Я бы предпочел разбить это на несколько функций. Код поиска по дереву начинается с пути типа ["links", "oracle", "usa", "midwest"]
и объекта данных со свойством массива children
, возвращающего узел по этому пути, или undefined
, если он не существует.
Тогда мы напишем простую оболочку для преобразования вашей строки "links.oracle.usa.0.midwest"
в этот массив и преобразования вашего входного массива в свойство children
нового объекта. Эта getNode
функция также возвращает узел или undefined
. Это независимо полезная функция.
Тогда, поскольку вы в конечном итоге захотите тип узла, мы добавим простую оболочку getType
для отчета о типе узла или "unknown"
, если он не найден. Мы можем легко заменить "unknown"
на undefined
или что угодно, что вы выберете очевидным образом.
const findInTree = (xs) => ([p = undefined, ...ps]) =>
xs == undefined
? undefined
: p == undefined
? xs
: findInTree (xs .children .find (({id}) => id == p)) (ps)
const getNode = (xs) => (path) =>
findInTree ({children: xs}) (path .split ('.') .filter (isNaN))
const getType = (xs) => (path) =>
(getNode (xs) (path) || {type: 'unknown'}) .type
const data = [{title: "Blogs", id: "blogs", type: "array", children: [{title: "Today", id: "today", type: "string"}, {title: "Yesterday", id: "yesterday", type: "enum", options: ["Y1", "Y2"]}]}, {title: "Links", id: "links", type: "object", children: [{title: "Oracle", id: "oracle", children: [{title: "USA", id: "usa", type: "array", children: [{title: "Midwest", id: "midwest", type: "enum", options: ["Md1", "Md2"]}, {title: "West", id: "west", type: "boolean"}]}, {title: "Asia", id: "asia", type: "array", children: [{title: "India", id: "india", type: "string"}]}]}]}];
console .log (getType (data) ("links.oracle.usa.0.midwest")) //~> "enum"
console .log (getType (data) ("links.oracle.usa")) //~> "array"
console .log (getType (data) ("blogs.0.today")) //~> "string"
console .log (getType (data) ("blogs.2.tomorrow")) //~> "unknown"
Все эти функции довольно просты. Рекурсия ясна; Распределение обязанностей должно быть простым.
Но я должен был сделать предположение здесь. Как указано в другом ответе, индекс массива и следующий идентификатор являются избыточными. Мы могли бы добавить сложности к рекурсивной функции, чтобы справиться с этим случаем, но это привело бы к уродливому коду. Вместо этого перед обработкой узла мы удаляем индекс массива. Вот для чего .filter (isNaN)
используется в getNode
. Если это нежелательное поведение, например, если вы захотите потерпеть неудачу или вернете undefined
, если индекс и идентификатор не совпадают, то нам придется сделать что-то совсем другое. Я действительно не следовал вашему обоснованию необходимости индекса и идентификатора, но в комментарии к другому ответу вы, похоже, подразумеваете, что это идентификатор, который вам действительно нужен. Если это и то и другое, то эта техника потребует тяжелой и ужасной модификации.