Вопрос:
У меня есть вложенный массив с неизвестной формой. Вот пример:
[«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 для прохождения каждого из элементов и возврата массива.