对表格多数组的环回响应/将对象的嵌套数组展平为线性数组
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));
【讨论】:
以上是关于对表格多数组的环回响应/将对象的嵌套数组展平为线性数组的主要内容,如果未能解决你的问题,请参考以下文章
将嵌套的 JSON 对象展平并排序到 javascript 中的数组中