我有一个对象例如:
{
test: {
a1: {
b1: "someText"
},
a2:2,
},
test2:{
a3:3,
a4:{
"b4": "otherText",
"b5": "textText"
}
}
}
我想迭代对象中的每个可能的键并创建一个新对象,其中键是一个相对路径,用下划线分隔,原始键和他的值。
例如:
{
test_a1_b1: 'someText',
test_a2: 2,
test2_a3: 3,
test2_a4_b4: 'otherText',
test2_a4_b5: 'texttext'
}
尝试了一些递归代码,但无法确定它。很高兴能得到你的帮助!
答案 0 :(得分:1)
这是List monad的一个很好的用例,又名Array.prototype.flatMap(第3阶段)
以下deepEntries
与Object.entries
的工作方式类似;它返回一个[ key, value ]
对的数组。
const deepEntries = (o = {}, path = []) =>
Object (o) === o
? Object.entries (o)
.flatMap
(([ k, v ]) => deepEntries (v, [ ...path, k ]))
: [ [ path, o ] ]
console.log (deepEntries (data))
// [ [ [ 'test', 'a1', 'b1' ], 'someText' ]
// , [ [ 'test', 'a2' ], 2 ]
// , [ [ 'test2', 'a3' ], 3 ]
// , [ [ 'test2', 'a4', 'b4' ], 'otherText' ]
// , [ [ 'test2', 'a4', 'b5' ], 'textText' ]
// ]
此结果优于您问题中的建议结果。如果由于某种原因你需要这种较小的形式,你可以很容易地得出它
deepEntries (data) .reduce
( (acc, [ keys, value ]) =>
({ ...acc, [keys .join ('_')]: value })
, {}
)
// { test_a1_b1: 'someText'
// , test_a2: 2
// , test2_a3: 3
// , test2_a4_b4: 'otherText'
// , test2_a4_b5: 'textText'
// }
如果您的环境中需要flatMap
,则可以轻松填充
Array.prototype.flatMap = function (f)
{ return this .reduce
( (acc, x) =>
acc .concat (f (x))
, []
)
}
在浏览器中运行以下程序以验证结果
Array.prototype.flatMap = function (f)
{ return this .reduce
( (acc, x) =>
acc .concat (f (x))
, []
)
}
const deepEntries = (o = {}, path = []) =>
Object (o) === o
? Object.entries (o)
.flatMap
(([ k, v ]) => deepEntries (v, [ ...path, k ]))
: [ [ path, o ] ]
const data =
{ test:
{ a1: { b1: "someText" }
, a2: 2
}
, test2 :
{ a3: 3
, a4:
{ b4: "otherText"
, b5: "textText"
}
}
}
console.log (deepEntries (data))
// [ [ [ 'test', 'a1', 'b1' ], 'someText' ]
// , [ [ 'test', 'a2' ], 2 ]
// , [ [ 'test2', 'a3' ], 3 ]
// , [ [ 'test2', 'a4', 'b4' ], 'otherText' ]
// , [ [ 'test2', 'a4', 'b5' ], 'textText' ]
// ]
const lesserResult =
deepEntries (data) .reduce
( (acc, [ keys, value ]) =>
({ ...acc, [keys .join ('_')]: value })
, {}
)
console.log (lesserResult)
// { test_a1_b1: 'someText'
// , test_a2: 2
// , test2_a3: 3
// , test2_a4_b4: 'otherText'
// , test2_a4_b5: 'textText'
// }