对表格多数组的环回响应/将对象的嵌套数组展平为线性数组
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));
我想将环回响应转换为 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));