Javascript – конвертировать вложенные массивы в объект массивов

Вопрос: У меня есть вложенный массив с неизвестной формой. Вот пример: ["head","val1","val2","val3", ["head2","val4","val5", ["head3","val6","val7", ["head4", "val8"],"val9"]], ["head5", "val10", "val11"] ] Все массивы имеют длину 2 или больше. Массив может содержать любое количество других массивов, которые также могут содержать любое количество массивов. Все значения являются строками или массивами. Я пытаюсь преобразовать это в один объект со

Вопрос:

У меня есть вложенный массив с неизвестной формой. Вот пример:

[«head»,»val1″,»val2″,»val3″, [«head2″,»val4″,»val5», [«head3″,»val6″,»val7», [«head4», «val8″],»val9»]], [«head5», «val10», «val11»] ]

Все массивы имеют длину 2 или больше. Массив может содержать любое количество других массивов, которые также могут содержать любое количество массивов. Все значения являются строками или массивами.

Я пытаюсь преобразовать это в один объект со следующей формой:

{«head»: [«val1″,»val2″,»val3», {«head2»: [«val4″,»val5», {«head3»: [«val6″,»val7», {«head4»: [«val8»]}, «val9»]}, {«head5»: [«val10», «val11»]} ]}

По сути, каждый массив должен быть преобразован в объект, где первое значение является ключом, а остальная часть массива является значением. Я пытался использовать reduce но не могу сделать все правильно.

Лучший ответ:

Что-то вроде этого?

function convert(arr) { if (arr instanceof Array) { const [key, …values] = arr; return { [key]: values.map(convert) }; } else { return arr; } } const test = [«head»,»val1″,»val2″,»val3″, [«head2″,»val4″,»val5», [«head3″,»val6″,»val7», [«head4», «val8″],»val9»]], [«head5», «val10», «val11»] ]; console.log(convert(test));Ответ №1

В этом случае вы не знаете, насколько глубоки ваши вложенные массивы, поэтому рекомендуется создать рекурсивную функцию.

В базовом случае вашей рекурсивной функции вход не является массивом, поэтому просто верните вход.

В случае, когда входные данные являются массивом, создайте объект JS с единственным свойством, имя которого равно первому элементу во входном массиве, а значение равно остальному массиву… Вам нужно рекурсивно вызвать Ваша функция против каждого из оставшихся членов, чтобы получить их значение в результирующем массиве.

var a = [«head»,»val1″,»val2″,»val3″, [«head2″,»val4″,»val5», [«head3″,»val6″,»val7», [«head4», «val8″],»val9»]], [«head5», «val10», «val11»] ]; function convert(val) { var result; if (Array.isArray(val)) { var key = val[0]; var vals = val.slice(1); result = {}; result[key] = []; for (var i = 0; i < vals.length; i++) { result[key].push(convert(vals[i])); } } else { result = val; } return result; } console.log(convert(a));Ответ №2

Просто сделайте это рекурсивно так:

function convert(arr) { return { [arr[0]]: arr.slice(1).map(item => Array.isArray(item)? convert(item): item) } }

Функция convert возвращает объект, связывающий одну пару ключ-значение. Ключом является arr[0] а значением являются остальные элементы в массиве (arr.slice(1)), сопоставленные с новым массивом, так что convert вызывается для всех элементов массива в этом массиве.

Версия ES5:

function convert(arr) { var obj = {}; obj[arr[0]] = arr.slice(1).map(function(item) { return item instanceof Array? convert(item): item; }); return obj; }

Пример:

function convert(arr) { return { [arr[0]]: arr.slice(1).map(item => Array.isArray(item)? convert(item): item) } } let arr = [«head»,»val1″,»val2″,»val3″, [«head2″,»val4″,»val5», [«head3″,»val6″,»val7», [«head4», «val8″],»val9»]], [«head5», «val10», «val11»] ]; let result = convert(arr); console.log(result);Ответ №3

ES6: вы можете сделать что-то вроде следующего

function convertArrayToObject(arr) { return Array.isArray(arr) && arr.length ? { [arr[0]]: arr.slice(1).map(convertArrayToObject) } : arr; }

Этот код определяет функцию convertArrayToObject которая возвращает сам элемент, если он не является массивом, или устанавливает первый элемент в качестве ключа и вызывает функцию if с оставшимися элементами в качестве значений, если это массив.

Ответ №4

Этот эффективный подход позволяет избежать использования slice() (который создаст временный массив размера N-1, который будет отброшен):

function change(a) { let b = []; for (let i = 1; i < a.length; i++) { let v = a[i]; b.push(Array.isArray(v) ? change(v) : v); } return {[a[0]]: b}; } console.log(change( [«head»,»val1″,»val2″,»val3″, [«head2″,»val4″,»val5», [«head3″,»val6″,»val7», [«head4», «val8″],»val9»]], [«head5», «val10», «val11»] ] ));Ответ №5

Поскольку вы пометили это с помощью lodash здесь также есть краткое решение:

var data = [«head»,»val1″,»val2″,»val3″, [«head2″,»val4″,»val5», [«head3″,»val6″,»val7», [«head4», «val8″],»val9»]], [«head5», «val10», «val11″] ] const f = (d) => ({[_.head(d)]: _.map(_.tail(d), x => _.isArray(x) ? f(x) : x)}) console.log(f(data))<script src=»https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js»></script>

Это рекурсивное решение, которое использует lodash .head для получения первого элемента массива, .tail для получения всего, кроме первого, а затем _.map для прохождения каждого из элементов и возврата массива.

Оцените статью
Добавить комментарий