对表格多数组的环回响应/将对象的嵌套数组展平为线性数组

Posted

技术标签:

【中文标题】对表格多数组的环回响应/将对象的嵌套数组展平为线性数组【英文标题】:Loopback Response to Tabular multi Array / Flattening nested Arrays of objects to linear Array 【发布时间】:2020-04-25 22:01:48 【问题描述】:

我想将 Loopback 响应转换为表格化/扁平化的多个数组(例如来自相邻 sql 查询而不是 loopback 的响应)。 样本输入:

let data = [
  id: 1,
  type: "sedan",
  vehicles: [
      id: 1,
      name: 'audi',
      tyres: [
          id: 1,
          size: "40inch",
          manufacturer: [
              id: 1,
              name: "General",
              branches: [
                  id: "1",
                  city: "munich"
                ,
                
                  id: "2",
                  city: "cologne"
                
              ]
            ,
            
              id: 2,
              name: "Rosana",
              branches: [
                  id: "3",
                  city: "paris"
                ,
                
                  id: "4",
                  city: "venice"
                
              ]
            
          ]
        ,
        
          id: 2,
          size: "60inch",
          manufacturer: [
            id: 1,
            name: "General",
            branches: [
                id: "1",
                city: "munich"
              ,
              
                id: "2",
                city: "cologne"
              
            ]
          ]
        
      ]
    ,
    
      id: 2,
      name: 'mercedes',
      tyres: [
        id: 2
        size: "60inch",
        manufacturer: [
          id: 1,
          name: "General",
          branches: [
              id: "1",
              city: "munich"
            ,
            
              id: "2",
              city: "cologne"
            
          ]
        ]
      ]
    
  ]
]

预期输出:

expectedOutput = [
    "id": 1,
    "type": "sedan",
    "vehicles.id.": 1,
    "vehicles.name": "audi",
    "tyres.id": 1,
    "tyres.size": "40inch",
    "manufacturer.id": 1,
    "manufacturer.name": "General",
    "branches.id": 1,
    "branches.city": "munich"
  ,
  
    "id": 1,
    "type": "sedan",
    "vehicles.id.": 1,
    "vehicles.name": "audi",
    "tyres.id": 1,
    "tyres.size": "40inch",
    "manufacturer.id": 1,
    "manufacturer.name": "General",
    "branches.id": 2,
    "branches.city": "cologne"
  ,
  
    "id": 1,
    "type": "sedan",
    "vehicles.id.": 1,
    "vehicles.name": "audi",
    "tyres.id": 1,
    "tyres.size": "40inch",
    "manufacturer.id": 2,
    "manufacturer.name": "Rosana",
    "branches.id": 3,
    "branches.city": "paris"
  ,
  
    "id": 1,
    "type": "sedan",
    "vehicles.id.": 1,
    "vehicles.name": "audi",
    "tyres.id": 1,
    "tyres.size": "40inch",
    "manufacturer.id": 2,
    "manufacturer.name": "Rosana",
    "branches.id": 4,
    "branches.city": "venice"
  ,
  
    "id": 1,
    "type": "sedan",
    "vehicles.id.": 2,
    "vehicles.name": "mercedes",
    "tyres.id": 1,
    "tyres.size": "60inch",
    "manufacturer.id": 1,
    "manufacturer.name": "General",
    "branches.id": 1,
    "branches.city": "munich"
  ,
  
    "id": 1,
    "type": "sedan",
    "vehicles.id.": 2,
    "vehicles.name": "mercedes",
    "tyres.id": 2,
    "tyres.size": "60inch",
    "manufacturer.id": 1,
    "manufacturer.name": "General",
    "branches.id": 2,
    "branches.city": "cologne"
  
]

我的代码如下,但是一旦调用递归或多次调用平面函数(没有递归),它就会以某种方式覆盖数据。 Flat 函数尝试在每次调用时展平 1 行/级别。也许有更好的递归方法,我没能找到。

function flat(arr, result) 
  arr.forEach(row => 
    let rows = [];
    keys = Object.keys(row);
    keys.forEach(key => 
      if (Array.isArray(row[key])) 
        rows.push(...merge(rows, row[key], key));
       else 
        rows.push(row);
      
    )

    result.push(...rows);
  )
  console.log(result);
// TODO 
   // flat(result, []);
  // each call linerize each level, 
  //should be called untill the whole array is linearized
   //

  return result;


function merge(rows, arr, alias) 
  if (!rows.length) 
    rows = []
  
  let a = arr.map(row => 
    keys = Object.keys(row);
    keys.forEach(key => 
      rows.forEach(r => 
        if (Array.isArray(row[key])) 
          r[key] = row[key];
         else 
          r[alias + '.' + key] = row[key];
        
        delete r[alias];
      )
    )
  )

  return a.filter(x=>
    if(x!== null)
      return x;
    
  );

【问题讨论】:

【参考方案1】:

我重写了扁平化数据的函数。使用数据对象和一个空字符串作为 keyPrefix 调用它。它保留完整的前缀,而不仅仅是最后一个父级(修复它应该是直截了当的)。

function deepCopy(obj) 
    return JSON.parse(JSON.stringify(obj)); // Can be replaced by a better way to deep copy


function isPrimitive(test) 
    return (test !== Object(test));


function compress(data, keyPrefix) 
    let response = ;

    if (isPrimitive(data)) 
        response[keyPrefix] = data;
    

    else if (Array.isArray(data)) 
        response = [];
        data.forEach(entry => 
            let compressed = compress(entry, keyPrefix);

            let item = ;

            if (Array.isArray(compressed)) 
                response.push.apply(response, compressed);
            

            else 
                Object.keys(compressed).forEach(key => 
                    item[key] = compressed[key];
                );

                response.push(item);
            
        );
    

    else 
        Object.keys(data).forEach(key => 
            let entry = data[key];

            let compressed = compress(entry, keyPrefix ? keyPrefix + "." + key : key);

            if (Array.isArray(compressed)) 
                if (!Array.isArray(response)) 
                    response = [response];
                

                let newItems = [];

                response.forEach(already => 
                    compressed.forEach(e => 
                        newItems.push(Object.assign(, deepCopy(already), e));
                    );
                );

                response = newItems;
            

            else 
                if (Array.isArray(response)) 
                    response.forEach(item => 
                        item = Object.assign(, deepCopy(item), compressed);
                    )
                

                else 
                    response = Object.assign(, deepCopy(response), compressed);
                
            
        );
    

    return response;

现在您可以在代码中调用此例程,如下所示:

compress(data, "");

或者如果你想查看它的输出:

// Prints the Output Object and uses 2 spaces as indentation
console.log(JSON.stringify(compress(data, ""), null, 2));

【讨论】:

以上是关于对表格多数组的环回响应/将对象的嵌套数组展平为线性数组的主要内容,如果未能解决你的问题,请参考以下文章

具有数组和字典混合的横向展平雪管数据

使用 jq 为 JSON 对象的嵌套数组中的属性展平数组

将嵌套的 JSON 对象展平并排序到 javascript 中的数组中

如何使用 pyspark 在 aws 胶水中展平嵌套 json 中的数组?

展平嵌套数组。 (爪哇)

展平/取消展平嵌套 JSON 对象的最快方法