我正在做一个小项目,我在某个特定的地方偶然发现了。疯狂的部分是,它看起来非常简单,但现在我要head头一个多小时。
我有一个示例对象,例如:
{
l1_1: {
l2_1: {
l3_1: 'l1_1_l2_1_l3_1',
l3_2: 'l1_1_l2_1_l3_2'
},
l2_2: {
l3_1: 'l1_1_l2_2_l3_1',
l3_2: 'l1_1_l2_2_l3_2'
},
l2_3: {
l3_1: 'l1_1_l2_3_l3_1',
l3_2: 'l1_1_l2_3_l3_2'
}
},
l1_2: {
l2_1: 'l1_2.l2_1',
l2_2: 'l1_2.l2_2'
}
}
我需要将每个路径输出到对象的最深子级,就像这样(作为单独的字符串):
l1_1.l2_1.l3_1
l1_1.l2_1.l3_2
l1_1.l2_2.l3_1
l1_1.l2_2.l3_2
l1_1.l2_3.l3_1
l1_1.l2_3.l3_2
l1_2.l2_1
l1_2.l2_2
问题在于,对于每个子对象,对象的深度可能不同。像提供的示例一样。 (它可能有2、3、4甚至5个级别)
这个想法是,我将使用这些字符串来检查对象是否在特定的临时文件中使用,它们使用以下语法{{ 'l1_1.l2_1.l3_1' | t }}
这是我现在要提出的。
const obj = {
l1_1: {
l2_1: {
l3_1: 'l1_1_l2_1_l3_1',
l3_2: 'l1_1_l2_1_l3_2'
},
l2_2: {
l3_1: 'l1_1_l2_2_l3_1',
l3_2: 'l1_1_l2_2_l3_2'
},
l2_3: {
l3_1: 'l1_1_l2_2_l3_1',
l3_2: 'l1_1_l2_2_l3_2'
}
},
l1_2: {
l2_1: 'l1_2.l2_1',
l2_2: 'l1_2.l2_2'
}
}
function iter(obj, keyTarget){
Object.keys(obj).forEach(function(key) {
const val = obj[key];
if(typeof val == 'object'){
keyTarget = keyTarget ? `${keyTarget}.${key}` : key;
iter(val, keyTarget)
} else {
keyTarget = `${keyTarget}.${key}`;
console.log(keyTarget)
}
});
}
iter(obj, false)
我知道代码为什么不起作用,因为循环在同一个对象上传递了多次,因此值在它们之间传递和共享,而我却得到了错误的值,但是我只是想不出一种解决方法清除字符串,并同时保留下一个对象。
任何见解都会受到赞赏。
答案 0 :(得分:5)
您可以收集路径,如果找到叶子,则将此路径添加到结果集中。
function getPathes(object, path = []) {
return Object
.entries(object)
.reduce((r, [k, v]) => r.concat(!v || typeof v !== 'object'
? path.concat(k).join('.')
: getPathes(v, path.concat(k))),
[]
);
}
var data = { l1_1: { l2_1: { l3_1: 'l1_1_l2_1_l3_1', l3_2: 'l1_1_l2_1_l3_2' }, l2_2: { l3_1: 'l1_1_l2_2_l3_1', l3_2: 'l1_1_l2_2_l3_2' }, l2_3: { l3_1: 'l1_1_l2_3_l3_1', l3_2: 'l1_1_l2_3_l3_2' } }, l1_2: { l2_1: 'l1_2.l2_1', l2_2: 'l1_2.l2_2' } },
pathes = getPathes(data);
console.log(pathes);
.as-console-wrapper { max-height: 100% !important; top: 0; }
另一种不存储路径的方法。
function getPathes(object, path = []) {
return Object
.entries(object)
.reduce(
(r, [k, v]) => r.concat(v && typeof v === 'object'
? getPathes(v).map(v => k + '.' + v)
: v
),
[]
);
}
var data = { l1_1: { l2_1: { l3_1: 'l1_1_l2_1_l3_1', l3_2: 'l1_1_l2_1_l3_2' }, l2_2: { l3_1: 'l1_1_l2_2_l3_1', l3_2: 'l1_1_l2_2_l3_2' }, l2_3: { l3_1: 'l1_1_l2_3_l3_1', l3_2: 'l1_1_l2_3_l3_2' } }, l1_2: { l2_1: 'l1_2.l2_1', l2_2: 'l1_2.l2_2' } },
pathes = getPathes(data);
console.log(pathes);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:2)
您可以使用reduce
方法创建递归函数以返回所有路径的数组。
const data = {"l1_1":{"l2_1":{"l3_1":"l1_1_l2_1_l3_1","l3_2":"l1_1_l2_1_l3_2"},"l2_2":{"l3_1":"l1_1_l2_2_l3_1","l3_2":"l1_1_l2_2_l3_2"},"l2_3":{"l3_1":"l1_1_l2_3_l3_1","l3_2":"l1_1_l2_3_l3_2"}},"l1_2":{"l2_1":"l1_2.l2_1","l2_2":"l1_2.l2_2"}}
function getPaths(data, prev = "") {
return Object.entries(data).reduce((r, [k, v]) => {
let path = prev + (prev.length ? '.' : '') + k
if (typeof v == 'object') r = r.concat(getPaths(v, path))
else r.push(path)
return r;
}, [])
}
const paths = getPaths(data)
console.log(paths)