从嵌套列表中组合对象
Posted
技术标签:
【中文标题】从嵌套列表中组合对象【英文标题】:Compose object from nested list 【发布时间】:2022-01-16 21:48:05 【问题描述】:我有一个从 XML 生成的通用 json。
"contextInfoDTOList": [
"key": "context_info",
"list": [
"key": "composition",
"list": [
"key": "parts",
"list": [
"key": "part",
"list": [
"list": [
"key": "materials",
"list": [
"key": "material",
"list": [
"key": "material_value",
"value": "100"
,
"key": "material_name",
"value": "polyester"
]
]
,
"key": "part_name",
"value": "LINING"
]
,
"list": [
"key": "materials",
"list": [
"key": "material",
"list": [
"key": "material_value",
"value": "100"
,
"key": "material_name",
"value": "cow leather"
]
]
,
"key": "part_name",
"value": "OUTER SHELL"
]
]
]
]
,
"key": "explanation"
]
]
我需要将信息提取成这样的:
COMPOSITION
Lining
100 % polyester
Outer Shell
100 % cow leather
我尝试了一种 forEach 方法,加入了键(成分、零件、材料...),但它变得很脏,我无法获得材料列表。
我正在考虑使用reduce来获取对象,但我不知道如何通过嵌套列表传递对象并使用递归。
想要的对象:
export class ContextInfo
composition: Composition;
explanation: string;
export class Composition
parts: Part[] = [];
export class Part
partName: string;
materials: Material[] = [];
export class Material
name: string;
value: number;
任何帮助将不胜感激。提前致谢!
【问题讨论】:
【参考方案1】:现在你有责任处理数据...
let contextInfoDTOList = [ key: "context_info", list: [ key: "composition", list: [ key: "parts", list: [ key: "part", list: [ list: [ key: "materials", list: [ key: "material", list: [ key: "material_value", value: "100" , key: "material_name", value: "polyester" ] ] , key: "part_name", value: "LINING" ] , list: [ key: "materials", list: [ key: "material", list: [ key: "material_value", value: "100" , key: "material_name", value: "cow leather" ] ] , key: "part_name", value: "OUTER SHELL" ] ] ] ] , key: "explanation" ] ]
function* getAllKeyValue(list = [], path = [])
for (let item of list)
if ("value" in item)
yield [item, path]
else
yield* getAllKeyValue(item.list, path.concat(item.key))
for (let [item, _path] of getAllKeyValue(contextInfoDTOList))
console.log(item);
// Todo: work with the data
【讨论】:
我认为这是查找所有叶键值对的好方法。但是,即使您还匹配到这些节点的路径,我认为它仍然会将大部分工作留在其他地方。换句话说,这是一种很好的方法,但可能对其他问题比对这个问题更有用。 (不过,我很乐意被证明是错误的。)【参考方案2】:这是一种非常难看的输入格式。但是通过不断过滤和查找节点,我们可以以相当合理的方式构建您的输出:
const byKey = (target) => (key) => key == target
const extract = (res) => res .contextInfoDTOList .filter (byKey ('context_info')) .map (info => (
explanation: info .list .find (byKey ('explanation')) .value,
composition: info .list .find (byKey ('composition')) .list .filter (byKey ('parts')) .map (parts => (
parts: parts .list .filter (byKey ('part')) .flatMap (p => p.list .map (q => q.list)) .map (part => (
partName: part .find (byKey ('part_name')) .value,
material: part .find (byKey ('materials')) .list .map (material => (
name: material .list .find (byKey ('material_name')) .value,
value: material .list .find (byKey ('material_value')) .value
))
))
))
))
const res = contextInfoDTOList: [key: "context_info", list: [key: "composition", list: [key: "parts", list: [key: "part", list: [list: [key: "materials", list: [key: "material", list: [key: "material_value", value: "100", key: "material_name", value: "polyester"]], key: "part_name", value: "LINING"], list: [key: "materials", list: [key: "material", list: [key: "material_value", value: "100", key: "material_name", value: "cow leather"]], key: "part_name", value: "OUTER SHELL"]]]], key: "explanation", value: "foobar"]]
console .log (extract (res))
.as-console-wrapper max-height: 100% !important; top: 0
(请注意,我必须向您的 "explanation"
节点添加一个虚拟的 "value"
以使其正确提取。如果我们不这样做,我们会得到一个 undefined
的解释。)
我们使用 helper byKey
只是为了减少函数体中的噪音。
【讨论】:
以上是关于从嵌套列表中组合对象的主要内容,如果未能解决你的问题,请参考以下文章