#javascript #arrays #recursion #multidimensional-array
Вопрос:
У меня есть вложенный массив, содержащий несколько строк на разных уровнях.
let nested = [
"ONE",
[
"TWO",
"THREE",
[
"FOUR",
"FIVE"
],
"SIX",
"SEVEN"
],
[
"HEIGHT"
],
"NINE"
]
У меня есть рабочая функция, которая может перемещаться по моему вложенному массиву для извлечения значения, используя массив индексов в качестве «иглы».:
const getValueByIndexes = (array,indexes) => {
const children = array[indexes[0]];
if(indexes.length > 1){
return getValueByIndexes(children,indexes.slice(1));
}else{
return children;
}
}
let test = getValueByIndexes(nested,[1,2,1]);
console.log(test); //this IS returning "FIVE", as expected
Это хорошо работает; но мой вопрос здесь в том, что мне нужна функция, которая СТРОИЛА БЫ эти иглы на основе моего вложенного массива.
Результат, который я хочу, это:
[
[0],//ONE
[1,0],//TWO
[1,1],//THREE
[1,2,0],//FOUR
[1,2,1],//FIVE
[1,3],//SIX
[1,4],//SEVEN
[2,0],//HEIGHT
[3],//NINE
]
Как я мог бы этого достичь ?
Спасибо!
Ответ №1:
Вы можете использовать повторный подход, проверяя наличие массивов.
const
getIndices = array => array.flatMap((v, i) => Array.isArray(v)
? getIndices(v).map(a => [i, ...a])
: [[i]]
),
data = ["ONE", ["TWO", "THREE", ["FOUR", "FIVE"], "SIX", "SEVEN"], ["HEIGHT"], "NINE"],
result = getIndices(data);
result.forEach(a => console.log(...a));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ответ №2:
Вы также можете использовать функцию рекурсивного генератора:
function* build_arr(d, c = []){
for (var i = 0; i < d.length; i ){
yield* (!Array.isArray(d[i]) ? [[...c, i]] : build_arr(d[i], [...c, i]))
}
}
let nested = ['ONE', ['TWO', 'THREE', ['FOUR', 'FIVE'], 'SIX', 'SEVEN'], ['HEIGHT'], 'NINE']
console.log(Array.from(build_arr(nested)))
Ответ №3:
Ответы от Нины Шольц и Ajax1234 оба замечательные. Но также нетрудно сделать это более общим способом для обработки произвольных объектов и их путей. Вот функция, которую я часто использую для этого:
const getLeafPaths = (obj) =>
Object (obj) === obj
? Object .entries (obj) .flatMap (
([k, v]) => getLeafPaths (v) .map (p => [Array .isArray (obj) ? Number(k) : k, ...p])
)
: [[]]
let nested = ["ONE", ["TWO", "THREE", ["FOUR", "FIVE"], "SIX", "SEVEN"], ["HEIGHT"], "NINE"]
console .log (getLeafPaths (nested))
//=> [[0], [1, 0], [1, 1], [1, 2, 0], [1, 2, 1], [1, 3], [1, 4], [2, 0], [3]]
.as-console-wrapper {max-height: 100% !important; top: 0}
Таким образом, это решает эту проблему, но это также полезно для других объектов:
getLeafPaths ({foo: 1, bar: {baz: [{qux: 2}, {quz: 3}], corge: 4}, grault: [5, 6, 7]})
даст:
[
["foo"],
["bar", "baz", 0, "qux"],
["bar", "baz", 1, "quz"],
["bar", "corge"],
["grault", 0],
["grault", 1],
["grault", 2]
]