提问人:Chris 提问时间:10/23/2023 最后编辑:Chris 更新时间:10/23/2023 访问量:123
一个属性的 JavaScript 数组总数
Total JavaScript Array by one Property
问:
我看了很多例子,但无法让它起作用。充其量,我最终会得到一个现有数组的版本,该版本复制了应该在摘要中丢失的属性。
我想为每个位置输出一个新的总计数组,并且不包括特定期间、期间属性等的任何详细信息。 我认为我的问题是 Object.assign({}, o);我正在创建一个完整的副本,但我看不到如何创建一个仅具有位置的对象,可以将总数添加到该位置。
这是一个简化的示例,在原版中,我将多个列相加并删除多个列。
let helper = {};
let locationPeriodCounts = [
{"period": "2023-10-21", "location": "228", "countIn": 6, "countOut": 1},
{"period": "2023-10-22", "location": "228", "countIn": 8, "countOut": 2},
{"period": "2023-10-23", "location": "228", "countIn": 3, "countOut": 3},
{"period": "2023-10-24", "location": "228", "countIn": 1, "countOut": 4},
{"period": "2023-10-21", "location": "229", "countIn": 5, "countOut": 6},
{"period": "2023-10-22", "location": "229", "countIn": 18, "countOut": 6},
{"period": "2023-10-23", "location": "229", "countIn": 8, "countOut": 6},
{"period": "2023-10-24", "location": "230", "countIn": 3, "countOut": 6},
{"period": "2023-10-25", "location": "230", "countIn": 4, "countOut": 6}
];
let locationCounts = locationPeriodCounts.reduce(function(r, o) {
let key = o.location;
if (!helper[key]) {
helper[key] = Object.assign({}, o); // create a copy of o
helper[key].totalCountIn = 0;
helper[key].totalCountOut = 0;
r.push(helper[key]);
} else {
helper[key].totalCountIn += o.countIn;
helper[key].totalCountOut += o.countOut;
}
return r;
}, []);
console.log(locationCounts);
这就是我正在寻找的输出......
[
{"location": "228", "totalCountIn": 18, "totalCountOut": 10},
{"location": "229", "totalCountIn": 31, "totalCountOut": 18},
{"location": "230", "totalCountIn": 7, "totalCountOut": 12}
];
答:
我添加了一个 Object.entries 以转换为对象数组
现在,我们需要将嵌套对象展开,使两个计数器与位置位于同一级别
let locationCounts = Object.entries(
locationPeriodCounts
.reduce(function (acc, { location, countIn, countOut }) {
acc[location] ??= { totalCountIn: 0, totalCountOut: 0 }; // create if it does not exist
acc[location].totalCountIn += countIn; // always add to the total
acc[location].totalCountOut += countOut; // always add to the total
return acc;
}, {})
)
.map(([location, { totalCountIn, totalCountOut }]) => ({ location, totalCountIn, totalCountOut }));
console.log(locationCounts);
<script>
let locationPeriodCounts = [
{"period": "2023-10-21", "location": "228", "countIn": 6, "countOut": 1},
{"period": "2023-10-22", "location": "228", "countIn": 8, "countOut": 2},
{"period": "2023-10-23", "location": "228", "countIn": 3, "countOut": 3},
{"period": "2023-10-24", "location": "228", "countIn": 1, "countOut": 4},
{"period": "2023-10-21", "location": "229", "countIn": 5, "countOut": 6},
{"period": "2023-10-22", "location": "229", "countIn": 18, "countOut": 6},
{"period": "2023-10-23", "location": "229", "countIn": 8, "countOut": 6},
{"period": "2023-10-24", "location": "230", "countIn": 3, "countOut": 6},
{"period": "2023-10-25", "location": "230", "countIn": 4, "countOut": 6}
];
</script>
评论
{ "228":0,"229":0,"230":0}
228
"location":"228"
18
"totalCount":18
我发现@mplungjan的反应比我的更聪明、更紧凑。 然而,这是我通常做的:
let locationPeriodCounts = [
{ "period": "2023-10-21", "location": "228", "countIn": 6 },
{ "period": "2023-10-22", "location": "228", "countIn": 8 },
{ "period": "2023-10-23", "location": "228", "countIn": 3 },
{ "period": "2023-10-24", "location": "228", "countIn": 1 },
{ "period": "2023-10-21", "location": "229", "countIn": 5 },
{ "period": "2023-10-22", "location": "229", "countIn": 18 },
{ "period": "2023-10-23", "location": "229", "countIn": 8 },
{ "period": "2023-10-24", "location": "230", "countIn": 3 },
{ "period": "2023-10-25", "location": "230", "countIn": 4 }
]
let locationCounts = locationPeriodCounts.reduce((acc, { location, countIn }) => {
let currLocationCount = acc.find(count => count.location === location)
if (currLocationCount) {
currLocationCount.totalCount += countIn
} else {
acc.push({
location: location,
totalCount: countIn
})
}
return acc;
}, []);
//If you also need sorting
locationCounts.sort((a, b) => {
//return a.totalCount - b.totalCount // asc
return b.totalCount - a.totalCount //desc
})
console.log(locationCounts);
这是输出:
[
{location: "229", totalCount: 31},
{location: "228", totalCount: 18},
{location: "230", totalCount: 7}
]
评论
find
acc[location]
acc
acc[location]
在原始代码中使用“helper”对象并不是一个坏的倾向,而常见的分组模式通过使用在传递给 的累加器对象中保存一个结果数组来做到这一点。这样做的好处包括:在reduce调用完成后不需要序列化对象,并且在reduce调用完成并检索结果数组后丢弃“helper”对象。reduce
reduce
let locationCounts = locationPeriodCounts.reduce(
(acc, { location, countIn, countOut }) => {
if (acc[location] === undefined) {
acc[location] = { location, totalCountIn: 0, totalCountOut: 0 };
acc._.push(acc[location]); // push a reference to the result array
}
acc[location].totalCountIn += countIn;
acc[location].totalCountOut += countOut;
return acc;
},
{ _: [] } // declare a result array in the accumulator
)._; // retrieve the result array
console.log(locationCounts);
<script>
let locationPeriodCounts = [
{"period": "2023-10-21", "location": "228", "countIn": 6, "countOut": 1},
{"period": "2023-10-22", "location": "228", "countIn": 8, "countOut": 2},
{"period": "2023-10-23", "location": "228", "countIn": 3, "countOut": 3},
{"period": "2023-10-24", "location": "228", "countIn": 1, "countOut": 4},
{"period": "2023-10-21", "location": "229", "countIn": 5, "countOut": 6},
{"period": "2023-10-22", "location": "229", "countIn": 18, "countOut": 6},
{"period": "2023-10-23", "location": "229", "countIn": 8, "countOut": 6},
{"period": "2023-10-24", "location": "230", "countIn": 3, "countOut": 6},
{"period": "2023-10-25", "location": "230", "countIn": 4, "countOut": 6}
];
</script>
无需解构
let locationCounts = locationPeriodCounts.reduce(
(acc, obj) => {
const key = obj.location;
if (acc[key] === undefined) {
acc[key] = {
location: obj.location,
totalCountIn: 0,
totalCountOut: 0,
};
acc._.push(acc[key]);
}
acc[key].totalCountIn += obj.countIn;
acc[key].totalCountOut += obj.countOut;
return acc;
},
{ _: [] }
)._;
console.log(locationCounts);
<script>
let locationPeriodCounts = [
{"period": "2023-10-21", "location": "228", "countIn": 6, "countOut": 1},
{"period": "2023-10-22", "location": "228", "countIn": 8, "countOut": 2},
{"period": "2023-10-23", "location": "228", "countIn": 3, "countOut": 3},
{"period": "2023-10-24", "location": "228", "countIn": 1, "countOut": 4},
{"period": "2023-10-21", "location": "229", "countIn": 5, "countOut": 6},
{"period": "2023-10-22", "location": "229", "countIn": 18, "countOut": 6},
{"period": "2023-10-23", "location": "229", "countIn": 8, "countOut": 6},
{"period": "2023-10-24", "location": "230", "countIn": 3, "countOut": 6},
{"period": "2023-10-25", "location": "230", "countIn": 4, "countOut": 6}
];
</script>
您现有的代码
您所缺少的只是创建一个仅具有相关属性的新对象(在您的问题中正确指出为问题)。要么使用上面的解构,要么像现在这样手动。Object.assign()
要使您自己的代码按原样工作,只需替换为 ,然后将求和移出块即可。这仍然在全局范围内徘徊,但通过将其作为闭包传递,可以很容易地解决:helper[key] = Object.assign({}, o);
helper[key] = { location: o.location };
else
helper
let locationCounts = (helper =>
locationPeriodCounts.reduce(function (r, o) {
let key = o.location;
if (!helper[key]) {
helper[key] = { location: o.location };
helper[key].totalCountIn = 0;
helper[key].totalCountOut = 0;
r.push(helper[key]);
}
helper[key].totalCountIn += o.countIn;
helper[key].totalCountOut += o.countOut;
return r;
}, []))({});
或使用上述设置。
评论