javascript 如何将数组对象转换为一个嵌套对象?

yeotifhr  于 2023-06-04  发布在  Java
关注(0)|答案(3)|浏览(306)

我有一个对象数组。每个对象指定其父对象的名称(如果有)。
我怎样才能把它变成一个单一的对象?我有麻烦处理2,3+层次的嵌套。
输出应该如下所示:

{ 
"REPORTING PERIOD": "2022",
"SIGNATURE DATE:" "20211055",
"HOUSE": 
  { "OWNER DATA":
    {"FIRST NAME": "Joe"},
    {"FIRST NAME": "Smith"}
  },
 {"VALUE HISTORY":
    {"INITAL PRICE": ...},
    {"LAST SALE PRICE": ...}
  },
 {"ADDRESS":
    {"STREET 1": ...},
    {"CITY": ...}
  },
}
"AGENT": 
 { etc. }
}

输入:

const data = [
    {
        "rank": 0,
        "key": "REPORTING PERIOD",
        "value": "2022",
        "parent": ""
    },
    {
        "rank": 0,
        "key": "SIGNATURE DATE",
        "value": "20211005",
        "parent": ""
    },
   
    {
        "rank": 0,
        "key": "HOUSE",
        "value": "",
        "parent": ""
    },
    {
        "rank": 1,
        "key": "OWNER DATA",
        "value": "",
        "parent": "HOUSE"
    },
    {
        "rank": 2,
        "key": "FIRST NAME",
        "value": "Joe",
        "parent": "OWNER DATA"
    },
    {
        "rank": 2,
        "key": "LAST NAME",
        "value": "Smith",
        "parent": "OWNER DATA"
    },
    {
        "rank": 1,
        "key": "VALUE HISTORY",
        "value": "",
        "parent": "HOUSE"
    },
    {
        "rank": 2,
        "key": "INITAL PRICE",
        "value": "12345",
        "parent": "VALUE HISTORY"
    },
    {
        "rank": 2,
        "key": "LAST SALE PRICE",
        "value": "1231236",
        "parent": "VALUE HISTORY"
    },
    {
        "rank": 1,
        "key": "ADDRESS",
        "value": "",
        "parent": "HOUSE"
    },
    {
        "rank": 2,
        "key": "STREET 1",
        "value": "5 MAIN TERRACE",
        "parent": "ADDRESS"
    },
    {
        "rank": 2,
        "key": "CITY",
        "value": "LONDON",
        "parent": "ADDRESS"
    },   
    {
        "rank": 0,
        "key": "AGENT",
        "value": "",
        "parent": ""
    },
    {
        "rank": 1,
        "key": "COMPANY DATA",
        "value": "",
        "parent": "AGENT"
    },
    {
        "rank": 2,
        "key": "COMPANY NAME",
        "value": "The Real Agent, Inc",
        "parent": "COMPANY DATA"
    },
    {
        "rank": 2,
        "key": "BUSINESS NUMBER",
        "value": "0021690080",
        "parent": "COMPANY DATA"
    },
    
    {
        "rank": 1,
        "key": "BUSINESS ADDRESS",
        "value": "",
        "parent": "AGENT"
    },
    {
        "rank": 2,
        "key": "STREET 1",
        "value": "800 MENLO STREET, SUITE 100",
        "parent": "BUSINESS ADDRESS"
    },
    {
        "rank": 2,
        "key": "CITY",
        "value": "MENLO PARK",
        "parent": "BUSINESS ADDRESS"
    },
    {
        "rank": 2,
        "key": "ZIP",
        "value": "94025",
        "parent": "BUSINESS ADDRESS"
    }  
]

我可以把所有东西都放到一个对象里,但是嵌套不能正常工作…Playground here

const resultObject: Record<string, unknown> = {};

//loop through array
for (const obj of data) {
    const { key, value, parent } = obj;

    if (parent === " " || parent === "" || parent === undefined) {
      resultObject[key] = value; // If parent is not specified, add it as a direct property in the result object
    } else {
        
      // If parent is specified, nest the element under its parent in the result object
      if (!resultObject[parent]) {
        resultObject[parent] = {}; // Create an empty object for the parent if it doesn't exist
      }
      (resultObject[parent] as Record<string, unknown>)[key] = value;
    }
  }
  console.log(resultObject);
tsm1rwdh

tsm1rwdh1#

您可以使用另一个查找对象来存储对每个对象的引用,从而无需嵌套循环即可轻松进行修改。

const res: Record<string, unknown> = {};
const lookup: typeof res = {};
for (const {key, value, parent} of data)
    ((parent ? lookup[parent] : res) as typeof res)[key] = lookup[key] = value || {};
console.log(res);

如果数据可以是任何顺序,并且除了空字符串之外可能存在其他错误值,那么您可以使用这种方法:

for (const {key, value, parent} of data)
    ((parent ? lookup[parent] ??= {} : res) as typeof res)[key] = 
        lookup[key] ??= value !== '' ? value : {};
vqlkdk9b

vqlkdk9b2#

您可以在reduce()调用的单次传递中使用相同的对象进行累积和查找,从而获得所需的树。通过访问返回对象上适当的顶级parent值来检索结果。这里使用nullish coalescing assignment (??=)检索/分配每个级别。

const data = [{"rank":0,"key":"REPORTING PERIOD","value":"2022","parent":""},{"rank":0,"key":"SIGNATURE DATE","value":"20211005","parent":""},{"rank":0,"key":"HOUSE","value":"","parent":""},{"rank":1,"key":"OWNER DATA","value":"","parent":"HOUSE"},{"rank":2,"key":"FIRST NAME","value":"Joe","parent":"OWNER DATA"},{"rank":2,"key":"LAST NAME","value":"Smith","parent":"OWNER DATA"},{"rank":1,"key":"VALUE HISTORY","value":"","parent":"HOUSE"},{"rank":2,"key":"INITAL PRICE","value":"12345","parent":"VALUE HISTORY"},{"rank":2,"key":"LAST SALE PRICE","value":"1231236","parent":"VALUE HISTORY"},{"rank":1,"key":"ADDRESS","value":"","parent":"HOUSE"},{"rank":2,"key":"STREET 1","value":"5 MAIN TERRACE","parent":"ADDRESS"},{"rank":2,"key":"CITY","value":"LONDON","parent":"ADDRESS"},{"rank":0,"key":"AGENT","value":"","parent":""},{"rank":1,"key":"COMPANY DATA","value":"","parent":"AGENT"},{"rank":2,"key":"COMPANY NAME","value":"The Real Agent, Inc","parent":"COMPANY DATA"},{"rank":2,"key":"BUSINESS NUMBER","value":"0021690080","parent":"COMPANY DATA"},{"rank":1,"key":"BUSINESS ADDRESS","value":"","parent":"AGENT"},{"rank":2,"key":"STREET 1","value":"800 MENLO STREET, SUITE 100","parent":"BUSINESS ADDRESS"},{"rank":2,"key":"CITY","value":"MENLO PARK","parent":"BUSINESS ADDRESS"},{"rank":2,"key":"ZIP","value":"94025","parent":"BUSINESS ADDRESS"}]

const tree = data.reduce((a, { parent, key, value }) => {
  (a[parent] ??= {})[key] = value === '' ? (a[key] ??= {}) : value;

  return a;
}, {})[''];

console.log(tree);
ecfdbz9o

ecfdbz9o3#

我们可以合并reduce和recursion。首先,从秩为0的没有父元素的元素开始。然后,使用reduce构建一个对象。如果数据数组中的对象没有值,那么它将是子对象的父对象,我们使用递归构建子对象。我们指定子级必须比当前级大一级,并且它应该将当前对象属性的键设置为父级。
请注意,这种方法允许数据条目不按顺序排列,而不是要求父项首先出现在数组中。它还遵守指定的等级,这意味着相同的密钥可以出现在多个等级级别,而不会破坏代码。

const data = [{"rank":0,"key":"REPORTING PERIOD","value":"2022","parent":""},{"rank":0,"key":"SIGNATURE DATE","value":"20211005","parent":""},{"rank":0,"key":"HOUSE","value":"","parent":""},{"rank":1,"key":"OWNER DATA","value":"","parent":"HOUSE"},{"rank":2,"key":"FIRST NAME","value":"Joe","parent":"OWNER DATA"},{"rank":2,"key":"LAST NAME","value":"Smith","parent":"OWNER DATA"},{"rank":1,"key":"VALUE HISTORY","value":"","parent":"HOUSE"},{"rank":2,"key":"INITAL PRICE","value":"12345","parent":"VALUE HISTORY"},{"rank":2,"key":"LAST SALE PRICE","value":"1231236","parent":"VALUE HISTORY"},{"rank":1,"key":"ADDRESS","value":"","parent":"HOUSE"},{"rank":2,"key":"STREET 1","value":"5 MAIN TERRACE","parent":"ADDRESS"},{"rank":2,"key":"CITY","value":"LONDON","parent":"ADDRESS"},{"rank":0,"key":"AGENT","value":"","parent":""},{"rank":1,"key":"COMPANY DATA","value":"","parent":"AGENT"},{"rank":2,"key":"COMPANY NAME","value":"The Real Agent, Inc","parent":"COMPANY DATA"},{"rank":2,"key":"BUSINESS NUMBER","value":"0021690080","parent":"COMPANY DATA"},{"rank":1,"key":"BUSINESS ADDRESS","value":"","parent":"AGENT"},{"rank":2,"key":"STREET 1","value":"800 MENLO STREET, SUITE 100","parent":"BUSINESS ADDRESS"},{"rank":2,"key":"CITY","value":"MENLO PARK","parent":"BUSINESS ADDRESS"},{"rank":2,"key":"ZIP","value":"94025","parent":"BUSINESS ADDRESS"}]

const f = (d, p='', r=0) => 
  d.filter(i => i.parent===p && i.rank===r)
  .reduce((a,c) => (a[c.key] = c.value || f(d, c.key, r+1), a), {})
  
console.log(f(data))

相关问题