我正在尝试找到一种解决方案,以获取嵌套JSON数组的特定格式。我尝试使用 Lodash groupBy 和 Javascript reduce ,但是我似乎找不到解决方案。
输入格式:
[
{
lineitem: {
id:1,
price: {
amount:100
},
supplierName:TestSupplier1
},
quantity:10
},
{
lineitem: {
id:2,
price: {
amount:200
},
supplierName:TestSupplier2
},
quantity:20
},
{
lineitem: {
id:3,
price: {
amount:300
},
supplierName:TestSupplier1
},
quantity:30
},
{
lineitem: {
id:4,
price: {
amount:400
},
supplierName:TestSupplier4
},
quantity:40
},
]
所需的输出格式:
[
{
TestSupplier1: [
{
id:1,
amount:100,
quantity:10
},
{
id:3,
amount:300,
quantity:30
}
],
TestSupplier2: [
{
id:2,
amount:200,
quantity:20
}
],
TestSupplier4: [
{
id:4,
amount:400,
quantity:40
}
]
]
我看到这里有3个步骤:
有人可以解决吗?
更新1
在按SupplierName成功分组之后,我现在想进一步展平阵列。这样,TestSupplier'X'就放置在每个数组中。
请参见以下示例:
[
{
supplierName:TestSupplier1,
id:1,
amount:100,
quantity:10
},
{
supplierName:TestSupplier1,
id:3,
amount:300,
quantity:30
},
{
supplierName:TestSupplier2,
id:2,
amount:200,
quantity:20
},
{
supplierName:TestSupplier4,
id:4,
amount:400,
quantity:40
}
]
答案 0 :(得分:0)
这应该可以使您获得所需的东西,唯一要注意的是您不能拥有带有多个相同键的对象,因此您需要一个对象数组而不是一个具有多个键的对象之lineItem
:
const result = data.reduce((result, item) => {
// Get the supplier name, id, amount and quantity of the current item
const supplierName = item.lineitem.supplierName;
const {
id,
price: { amount }
} = item.lineitem;
const { quantity } = item;
const lineItem = {
id,
amount,
quantity
};
// If it already exists in the result, add the data to the existing key
if (Object.keys(result).includes(supplierName)) {
return Object.assign({}, result, {
[supplierName]: [...result[supplierName], lineItem]
});
} else {
// Otherwise create a new key
return Object.assign({}, result, { [supplierName]: [lineItem] });
}
}, {});
这给您:
{ TestSupplier1:
[ { id: 1, amount: 100, quantity: 10 },
{ id: 3, amount: 300, quantity: 30 } ],
TestSupplier2: [ { id: 2, amount: 200, quantity: 20 } ],
TestSupplier4: [ { id: 4, amount: 400, quantity: 40 } ] }
在最初的问题中,您要求将整个内容包装在一个数组中,这显然很简单,例如[result]
。
答案 1 :(得分:0)
let resObj = {};
data.forEach( el => {
if(!Object.keys(resObj).includes(el.lineitem.supplierName))
{
console.log(el);
resObj[el.lineitem.supplierName] = [];
}
let newInnerObj = { id: el.lineitem.id, amount: el.lineitem.price.amount, quantity: el.quantity };
resObj[el.lineitem.supplierName].push(newInnerObj);
});
console.log(resObj);
这是一个简单的答案,但是就像我在评论中说的那样-您不能具有具有相同名称的属性的对象,因此结果是一个对象,其属性为TestSupplierX
,每个属性具有所需结构的对象数组。
这实际上就像遍历所有原始数组并构造正确的对象一样简单。我认为您想念的是如何将它们设置为来自providerName的正确属性名称,而这仅通过检查结果对象是否已经使用Object.keys(obj).includes(key)
来完成,以及是否不创建它来完成。只需访问它并将其初始化为一个空数组即可。
答案 2 :(得分:0)
如果您使用TypeScript,以下操作可能会有所帮助:
interface IInput {
lineitem: {
id: number;
price: {
amount: number;
}
supplierName: string;
}
quantity: number;
}
interface IOutputA {
[key: string]: {
id: number;
amount: number;
quantity: number;
}[];
}
interface IOutputB {
supplierName: string;
id: number;
amount: number;
quantity: number;
}
function transformA(input: IInput[]): IOutputA {
const ret: IOutputA = {};
input.forEach(it => {
ret[it.lineitem.supplierName] = [];
ret[it.lineitem.supplierName].push({
id: it.lineitem.id,
amount: it.lineitem.price.amount,
quantity: it.quantity,
}
}
return ret;
}
function transformB(outputA: IOutputA): IOutputB {
const ret: IOutputB = [];
Object.keys(outputA).forEach(x => {
outputA[x].forEach(y => {
ret.push({
supplierName: x,
id: y.id,
amount: y.amount,
quantity: y.quantity,
});
});
});
return ret;
}
很高兴看到您也尝试解决此问题。