如何将长度可变的数组转换为 javascript 中的嵌套 object 树
How to turn an array of arrays with varying length into a nested object tree in javascript
我需要处理结构类似于
的文件
Title
/foo/bar/foo/bar 1
/foo/bar/bar 2
/bar/foo 3
/bar/foo/bar 4
通过在每个 / 和 \n 处拆分,很容易将其解析为数组数组。但是,一旦我得到一个数组数组,我就想不出将其转换为嵌套 object 的好方法。所需格式:
{
Title,
{
foo: {
bar: {
foo: {
bar: 1
},
bar: 2
}
},
bar: {
foo: {
3,
bar: 4
}
}
}
}
这似乎是一件非常常见的事情,所以我完全不明白为什么我找不到任何 pre-existing 解决方案。我有点希望 javascript 甚至为此具有本机函数,但合并 objects 显然会覆盖值,而不是默认情况下嵌套 object。我尝试了以下方法,利用 jQuery.extend(),但它实际上并没有结合 like-terms(即 parents 和 grand-parents)。
let array = fileContents.split('\n');
let object = array.map(function(string) {
const result = string.split('/').reduceRight((all, item) => ({
[item]: all
}), {});
return result;
});
output = $.extend(true, object);
console.log(JSON.stringify(output));
这将数组的数组变成了嵌套的 object,但没有合并 like-terms...
我可以 brute-force 这个,但是我的 real-world 问题有超过 2000 行,深入 5 层(/foo/foo/foo/foo value value value),实际上有一个 space-separated 值数组而不是每行一个值。我愿意像对待字符串一样对待值数组,只是假装它不是数组,但至少在不编写 hefty/primitive 算法的情况下正确嵌套 object 真的很好。
由于这基本上就是子目录的组织方式,因此看起来应该很容易。有没有我没有看到的相对简单的解决方案?
您可以减少 keys/value 的数组并使用所有键设置值。
如果没有提供密钥,它将取而代之。
const
setValue = (target, keys, value) => {
const last = keys.pop();
keys.reduce((o, k) => o[k] ??= {}, target)[last] = value;
return target;
},
data = 'Title\n/foo/bar/foo/bar 1\n/foo/bar/bar 2\n/bar/foo 3\n/bar/foo/bar 4',
result = data
.split(/\n/)
.reduce((r, line) => {
const [keys, value] = line.split(' ');
return setValue(r, keys.split('/').filter(Boolean), value || keys);
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我需要处理结构类似于
的文件Title
/foo/bar/foo/bar 1
/foo/bar/bar 2
/bar/foo 3
/bar/foo/bar 4
通过在每个 / 和 \n 处拆分,很容易将其解析为数组数组。但是,一旦我得到一个数组数组,我就想不出将其转换为嵌套 object 的好方法。所需格式:
{
Title,
{
foo: {
bar: {
foo: {
bar: 1
},
bar: 2
}
},
bar: {
foo: {
3,
bar: 4
}
}
}
}
这似乎是一件非常常见的事情,所以我完全不明白为什么我找不到任何 pre-existing 解决方案。我有点希望 javascript 甚至为此具有本机函数,但合并 objects 显然会覆盖值,而不是默认情况下嵌套 object。我尝试了以下方法,利用 jQuery.extend(),但它实际上并没有结合 like-terms(即 parents 和 grand-parents)。
let array = fileContents.split('\n');
let object = array.map(function(string) {
const result = string.split('/').reduceRight((all, item) => ({
[item]: all
}), {});
return result;
});
output = $.extend(true, object);
console.log(JSON.stringify(output));
这将数组的数组变成了嵌套的 object,但没有合并 like-terms... 我可以 brute-force 这个,但是我的 real-world 问题有超过 2000 行,深入 5 层(/foo/foo/foo/foo value value value),实际上有一个 space-separated 值数组而不是每行一个值。我愿意像对待字符串一样对待值数组,只是假装它不是数组,但至少在不编写 hefty/primitive 算法的情况下正确嵌套 object 真的很好。
由于这基本上就是子目录的组织方式,因此看起来应该很容易。有没有我没有看到的相对简单的解决方案?
您可以减少 keys/value 的数组并使用所有键设置值。
如果没有提供密钥,它将取而代之。
const
setValue = (target, keys, value) => {
const last = keys.pop();
keys.reduce((o, k) => o[k] ??= {}, target)[last] = value;
return target;
},
data = 'Title\n/foo/bar/foo/bar 1\n/foo/bar/bar 2\n/bar/foo 3\n/bar/foo/bar 4',
result = data
.split(/\n/)
.reduce((r, line) => {
const [keys, value] = line.split(' ');
return setValue(r, keys.split('/').filter(Boolean), value || keys);
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }