[英]How to reduce nested JSON data structure into a map JavaScript
I've implemented a solution for the problem below with loops, but I'm sure there is a better way. 我已经用循环实现了下面问题的解决方案,但我确信有更好的方法。 Consider this data structure: 考虑这个数据结构:
let arr = [
{
"id": "000701",
"status": "No Source Info",
"sources": []
},
{
"id": "200101",
"status": "Good",
"sources": [
{
"center": "H2",
"uri": "237.0.1.133",
"program": 1,
"status": "Good",
"state": {
"authState": "authorized",
"lockState": "locked"
}
}
]
},
{
"id": "005306",
"status": "Good",
"sources": [
{
"center": "H1",
"uri": "237.0.6.5",
"program": 3,
"status": "Good",
"state": {
"authState": "authorized",
"lockState": "locked"
}
},
{
"center": "H1",
"uri": "237.0.6.25",
"program": 3,
"status": "Good",
"state": {
"authState": "authorized",
"lockState": "locked"
}
}
]
}
]
I want to learn the most efficient way to reduce it to a map with key-value pairs of only the nested uri
and state
values from the sources
array. 我想学习一种最有效的方法,将它减少到一个映射,只使用来自sources
数组的嵌套uri
和state
值的键值对。 The final result should look like this: 最终结果应如下所示:
let stateMap = {
"237.0.1.133": { "authState": "authorized", "lockState": "locked" },
"237.0.6.5": { "authState": "authorized", "lockState": "locked" },
"237.0.6.25": { "authState": "authorized", "lockState": "locked" }
}
I have a partial solution that returns a map of each source
array, but I'm struggling to get it all into one structure. 我有一个部分解决方案,返回每个source
数组的映射,但我很难将它全部集成到一个结构中。
let allStates = arr.reduce((acc, object) => {
if (object.sources.length) {
let sourceMap = object.sources.reduce((map, obj) => {
map[obj.uri] = obj.state
return map
}, {})
acc[acc.length] = sourceMap
return acc
}
// delete all unused keys and somehow flatten the objects?
}, {})
Would recursion be an option here or what would be a better approach? 递归是一个选项在这里或什么是更好的方法?
The code below first performs a flatMap
operation on the nested sources
arrays, and then reduces everything to your desired result object: 下面的代码首先对嵌套的sources
数组执行flatMap
操作,然后将所有内容减少到所需的结果对象:
const result = arr.reduce((a, {sources}) => [...a, ...sources], [])
.reduce((a, {uri, state}) => ({...a, [uri]: state}), {});
Complete snippet: 完整代码段:
const arr = [{ "id": "000701", "status": "No Source Info", "sources": [] }, { "id": "200101", "status": "Good", "sources": [{ "center": "H2", "uri": "237.0.1.133", "program": 1, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } }] }, { "id": "005306", "status": "Good", "sources": [{ "center": "H1", "uri": "237.0.6.5", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } }, { "center": "H1", "uri": "237.0.6.25", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } } ] } ]; const result = arr.reduce((a, {sources}) => [...a, ...sources], []) .reduce((a, {uri, state}) => ({...a, [uri]: state}), {}); console.log(result)
You could reduce the outer array and iterate sources
and update an object as result set. 您可以减少外部数组并迭代sources
并更新对象作为结果集。
var data = [{ id: "000701", status: "No Source Info", sources: [] }, { id: "200101", status: "Good", sources: [{ center: "H2", uri: "237.0.1.133", program: 1, status: "Good", state: { authState: "authorized", lockState: "locked" } }] }, { id: "005306", status: "Good", sources: [{ center: "H1", uri: "237.0.6.5", program: 3, status: "Good", state: { authState: "authorized", lockState: "locked" } }, { center: "H1", uri: "237.0.6.25", program: 3, status: "Good", state: { authState: "authorized", lockState: "locked" } }] }], stateMap = data.reduce( (o, { sources }) => (sources.forEach(({ uri, state }) => o[uri] = state), o), Object.create(null) ); console.log(stateMap);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Would recursion be an option here or what would be a better approach? 递归是一个选项在这里或什么是更好的方法?
No, because you have only one single nested level. 不,因为您只有一个嵌套级别。
you can use nested reduce one for getting the uri map from the item in the list, other for getting the value of sources map. 您可以使用嵌套的reduce来从列表中的项目获取uri映射,其他用于获取源映射的值。
const mappedArray = arr.reduce((acc, item) => ({
...acc,
...item.sources.reduce((accSource, itemSource) => ({
...accSource,
[itemSource.uri]: itemSource.state,
}), {})
}), {})
let arr = [ { "id": "000701", "status": "No Source Info", "sources": [] }, { "id": "200101", "status": "Good", "sources": [ { "center": "H2", "uri": "237.0.1.133", "program": 1, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } } ] }, { "id": "005306", "status": "Good", "sources": [ { "center": "H1", "uri": "237.0.6.5", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } }, { "center": "H1", "uri": "237.0.6.25", "program": 3, "status": "Good", "state": { "authState": "authorized", "lockState": "locked" } } ] } ] const mappedArray = arr.reduce((acc, item) => ({ ...acc, ...item.sources.reduce((accSource, itemSource) => ({ ...accSource, [itemSource.uri]: itemSource.state, }), {}) }), {}) console.log(mappedArray)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.