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

Loopback Response to Tabular multi Array / Flattening nested Arrays of objects to linear Array

我想将环回响应转换为 tabularize/flattened 多个数组(例如来自相邻 sql 查询的响应而不是环回)。 示例输入:

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 row/level 变平。也许有更好的递归方法我没能接触到。

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;
    }
  });

我重写了扁平化数据的函数。使用数据对象和一个空字符串作为 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));