我有一个形状未知的嵌套数组。这是一个示例:
["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
,但不太正确。
答案 0 :(得分:3)
在这种情况下,您不知道嵌套数组的深度,因此设计递归函数是个好主意。
在递归函数的基本情况下,输入不是数组,因此只需返回输入即可。
在输入为数组的情况下,请创建一个具有单个属性的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));
答案 1 :(得分: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
。 / p>
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);
答案 2 :(得分:1)
像这样吗?
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));
答案 3 :(得分:0)
ES6:您可以执行以下操作
export class SomeClass {
// Navigate To
constructor() {
console.log("1. constructor")
}
canActivate() {
console.log("2. canActivate")
}
activate() {
console.log("3. activate")
}
attached() {
// Page has loaded
console.log("4. attached")
}
// Navigate Away
canDeactivate() {
console.log("1. canDeactivate")
}
deactivate() {
console.log("2. deactivate")
}
detached() {
console.log("3. detached")
}
}
此代码定义了一个函数function convertArrayToObject(arr) {
return Array.isArray(arr) && arr.length ? {
[arr[0]]: arr.slice(1).map(convertArrayToObject)
} : arr;
}
,如果它不是数组,则返回元素本身,或者将第一个元素设置为键,如果是数组,则以其余元素作为值调用该函数。
答案 4 :(得分:0)
这种有效的方法避免使用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 :(得分:0)
由于您用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
遍历每个元素并返回一个数组。