英文:
How to use ES6 reduce to sum values across another property
问题
Here's the translated part of your text:
我有一个这样的数组:
const products =
[{product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5}],
[{product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}]
我需要对它们求和,并确保每个产品的体积不超过另一个具有相同结构的对象:
const ProductLimits: ProductVolumes[] = [{product: "a", volume: 10}, {product: "b", volume: 22}, {product: "c", volume: 12}]
已经使用了以下方法:
products.flatMap(x => x.map(y => {
return { product: y.product, volume: y.volume }
}));
这将第一个数组的数组展平为单一数组:
[{product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5},
{product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}]
然后,为了进行求和,我正在使用:
.reduce((acc: IInterface, i) => {
acc[i.product] = (acc[i.product] || 0) + i.volume;
return acc;
});
使用:
interface IInterface {
product: string;
volume: number;
[product: string]: any;
}
因为TypeScript要求索引签名。
然而,问题是reduce在第一次迭代后返回了一个正确的产品列表,除了第一个产品,经过3次迭代后它变成了:
product: "a"
volume: 3
b: 7
c: 5
问题显然出现在acc的第一个值的结构上。
有没有关于如何修复第一次迭代或更好方法的想法?
英文:
I have an array in this form:
const products =
[{product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5}],
[{product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}]
and I need to sum them and make sure the volumes for each product are not more than in another object with the same structure:
const ProductLimits: ProductVolumes[] = [{product: "a", volume: 10}, {product: "b", volume: 22}, {product: "c", volume: 12}]
Have used
products.flatMap(x => x.map(y => {
return { product: y.product, volume: y.volume }}));
which flattens the first array of arrays to a single array:
[{product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5},
{product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}]
Then, in order to do the summing, I'm doing
.reduce(acc: IInterface, i) => {
acc[i.product] = acc[i.product] || 0) + i.volume;
return acc;
});
using
interface IInterface {
product: string;
volume: number;
[product: string]: any;
}
since Typescript demands an index signature.
However the problem is the reduce is returning a correct list of products except for the first one, where after 3 iterations it has:
product: "a"
volume: 3
b: 7
c: 5
The issue is clearly with the structure of the first value of acc.
Any ideas on how to fix that first iteration or of a better approach?
答案1
得分: 2
You can just use flat()
to flatten the array. Then you need to seed/ initialized reduce()
to an empty object {}
, then the aggregation should work (you need to fix that missing bracket!). Last but not least you just need to map the aggregated values into the desired target structure using Object.entries()
.
Note I am also ussing a nullish coalescing assignment as I think this is more readable then working with falsy values.
英文:
You can just use flat()
to flatten the array. Then you need to seed/ initialized reduce()
to an empty object {}
, then the aggregation should work (you need to fix that missing bracket!). Last but not least you just need to map the aggregated values into the desired target structure using Object.entries()
.
Note I am also ussing a nullish coalescing assignment as I think this is more readable then working with falsy values.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const input = [
[{
product: "a",
volume: 3
}, {
product: "b",
volume: 7
}, {
product: "c",
volume: 5
}],
[{
product: "a",
volume: 8
}, {
product: "b",
volume: 10
}, {
product: "c",
volume: 4
}]
];
const aggregated = input.flat()
.reduce((acc, i) => {
acc[i.product] = (acc[i.product] ??= 0) + i.volume;
return acc;
}, {});
const output = Object.entries(aggregated).map(([product, volume]) => ({ product, volume }));
console.log(output)
<!-- end snippet -->
答案2
得分: 0
I can provide the translation of the code snippet you provided:
// 开始代码片段:不隐藏,显示控制台,不使用Babel
// JavaScript 语言
let products = [[{product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5}], [{product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}]]
let SingleArray = products.flat()
function Customfun(){
let map = new Map();
let type = "";
for(let obj of SingleArray){
if(map.has(obj.product)){
let vol = map.get(obj.product)
map.set(obj.product,obj.volume+vol);
}
else{
map.set(obj.product,obj.volume);
}
}
let ProductsList = [];
for(let [key,val] of map.entries()){
ProductsList = [...ProductsList,{product:key, volume:val}]
}
return ProductsList;
}
console.log(Customfun())
// 结束代码片段
Please note that I've translated the code itself while keeping the code structure intact.
英文:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let products = [[{product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5}], [{product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}]]
let SingleArray = products.flat()
function Customfun(){
let map = new Map();
let type = "";
for(let obj of SingleArray){
if(map.has(obj.product)){
let vol = map.get(obj.product)
map.set(obj.product,obj.volume+vol);
}
else{
map.set(obj.product,obj.volume);
}
}
let ProductsList = [];
for(let [key,val] of map.entries()){
ProductsList = [...ProductsList,{product:key, volume:val}]
}
return ProductsList;
}
console.log(Customfun())
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论