我有以下对象结构:
{
a: {
b: "abc",
c: [
{
d: "pqr",
e: true
},
{
f: 1,
e: ["xyz", 1]
}
]
}
}
现在我想以预期输出中显示的特定格式转换这些结构。
我试图遍历上面的结构,但构造的路径不正确 这就是我正在做的事情
const getFinalNode = function(data, path){
if (typeof data === 'object'){
for (let key in data) {
// console.log(key);
if (typeof data[key] === 'object'){
path += key+'/'
getFinalNode(data[key], path)
// console.log(true);
}else{
console.log({
value: data[key],
key: key,
path:path
})
}
}
}
}
getFinalNode(data, "");
我的预期输出应为
[
{
name: "b",
value: "abc",
path: "a/b"
},
{
name: "d",
value: "pqr",
path: "a/c/0/d"
},
{
name: "e",
value: true,
path: "a/c/0/e"
},
{
name: "f",
value: 1,
path: "a/c/1/f"
},
{
name: "e",
value: 'xyz',
path: "a/c/1/e"
},
{
name: "e",
value: 1,
path: "a/c/1/e"
}
]
那么我如何遍历上面的结构并将其转换为预期的输出,或者我可以在现有代码中使用任何解决方案。
现在我得到以下输出
答案 0 :(得分:0)
您应该将path
和累积的数组acc
传递给getFinalNode
的递归调用:
const getFinalNode = function(data, acc = [], path = "") { // default values for acc and path, so we won't bother ourselves with that
for(let key in data) { // for each key in the object/array data
if(data.hasOwnProperty(key)) { // if this is an own property
if(data[key] && typeof(data[key]) === "object") { // if the value of the current property is an object/array (not null: typeof null === "object")
getFinalNode(data[key], acc, path + "/" + key); // then traverse it, passing acc to add to what we already have
} else { // otherwise
acc.push({ // make a leaf object and push it to the accumulator acc
path: path.slice(1) + "/" + key, // slice to remove the first "/" from path
name: key,
value: data[key]
});
}
}
}
return acc;
}
let data = {"a":{"b":"abc","c":[{"d":"pqr","e":true},{"f":1,"e":["xyz",1]}]}};
let result = getFinalNode(data);
console.log(result);
答案 1 :(得分:0)
你只需要通过一个阵列,然后对你正在建造的路径做一点调整。
在最终路径中包含最后一项有点令人惊讶,并进行了一些额外的调整,但我认为这是你在结果中寻找的内容。
const getFinalNode = function(data, path, result){
result = result || [];
// This check isn't needed if the initial call will always be an object.
if (typeof data === 'object'){
for (let [key, val] of Object.entries(data)) {
if (typeof val === 'object'){
getFinalNode(val, path ? (path + "/" + key) : key, result);
}else{
const notNum = isNaN(key);
result.push({
name: notNum ? key : path.slice(path.lastIndexOf("/") + 1),
value: val,
path:path + (notNum ? "/" + key : "")
});
}
}
}
return result;
}
const data = {
a: {
b: "abc",
c: [
{
d: "pqr",
e: true
},
{
f: 1,
e: ["xyz", 1]
}
]
}
};
console.log(getFinalNode(data, ""));

我在Object.entries()
中使用for-of
进行了解构赋值,只是为了方便将键和值赋给变量。您原来的for-in
循环也很好。
答案 2 :(得分:0)
有两件事你没有得到预期的输出: - 当数据[“key”]不是对象时,您不添加路径 - 您正在寻找获得数组输出但是您要分开打印每个元素。
看着你想要的输出我看到路径总是包括b,即使b和c是兄弟姐妹,并且不允许它们都在同一个路径中。把这作为打字错误,我修改了一下脚本以获得正确的输出:
var data = {a: { b: "abc", c: [ { d: "pqr", e: true},{ f: 1, e: ["xyz", 1] }]}};
var output = [];
getFinalNode = function(data, path){
if (typeof data === 'object'){
for (let key in data) {
// console.log(key);
path.push(key)
getFinalNode(data[key], path)
// console.log(true);
if (typeof data[key] != 'object'){
output.push({
value: data[key],
key: key,
path:path.join("/")
});}
}
}
path.splice(-1,1)
}
getFinalNode(data, []);
console.log(output);
答案 3 :(得分:0)
对于有趣,肮脏的解决方案,孩子们不会在家里这样做!
function getFinalNode(node) {
return (function rec(obj, path='', results=[]) {
path = path && (path + '/')
return Object.entries(obj)
.reduce((arr, [name, value]) => void (typeof value === 'object'
? rec(value, path + name, arr)
: arr.push({ name, value, path: path + name })) || arr,
results)
})(node)
}
console.log(getFinalNode({a:{b:"abc",c:[{d:"pqr",e:true},{f:1,e:["xyz",1]}]}}))
解释一下:
path = path && (path + '/')
如果path
为空,则将评估条件的第一部分,因此将得到一个空字符串。否则,将评估第二部分,并进行连接。
void (whatEverExpression) || arr
void将使whatEverExpression返回未定义,因此将返回arr
。
(这是一个技巧,在减少某些东西时我觉得很少。即使ESLint禁止使用void:D)
编辑:受摇滚明星答案的启发,entries
,甚至更好:D
答案 4 :(得分:0)
您可以使用函数来收集项目,并使用函数进行递归调用以迭代对象。
function traverse(object) {
function iter(o, p) {
Object.keys(o).forEach(function (k) {
if (o[k] && typeof o[k] === 'object') {
return iter(o[k], p.concat(k));
}
result.push({ name: k, value: o[k], path: p.join('/') });
});
}
var result = [];
iter(object, []);
return result;
}
var object = { a: { b: "abc", c: [{ d: "pqr", e: true }, { f: 1, e: ["xyz", 1] }] } };
console.log(traverse(object));
.as-console-wrapper { max-height: 100% !important; top: 0; }