跳转到内容

对对象数组的指定一个或多个键的值进行求和

/**
* 对对象数组中指定的一个或多个键进行求和,跳过不存在或非有效数字的值。
*
* @param arr - 要遍历的对象数组。
* @param keys - 需要求和的属性键数组。
* @returns 返回一个 Record<string, number>,其中每个键对应输入 keys 中的项,值为该键在数组中所有有效数字的和。
*
* @remarks
* - 仅对 typeof value === "number" 且 Number.isFinite(value) 的值进行累加。
* - 如果某个键在数组中没有任何有效数字,会在控制台发出警告并将该键的结果设为 0。
* - 如果某个键存在部分无效或缺失的值,会跳过这些元素并在控制台警告被跳过的数量。
*
* @example
* const data = [{ a: 1 }, { a: 2 }, { a: "x" }];
* // 返回 { a: 3 },并在控制台警告有 1 个值被跳过
* sumKeysInObjects(data, ["a"]);
*/
export const sumKeysInObjects = (
arr: Record<string, any>[],
keys: string[]
): Record<string, number> => {
const result: Record<string, number> = {};
for (const key of keys) {
let sum = 0;
let validCount = 0;
for (const obj of arr) {
if (obj && Object.prototype.hasOwnProperty.call(obj, key)) {
const value = obj[key];
if (typeof value === "number" && Number.isFinite(value)) {
sum += value;
validCount++;
} // 否则跳过该值
} // 键不存在也跳过
}
if (validCount === 0) {
console.warn(`键 "${key}" 在数组中没有有效数字,结果为 0。`);
result[key] = 0;
} else {
if (validCount < arr.length) {
console.warn(
`键 "${key}" 有 ${arr.length - validCount} 个值被跳过(不存在或非有效数字)。`
);
}
result[key] = sum;
}
}
return result;
};
const data1 = [
{ a: 32, b: 64, c: "不知道" },
{ a: 32 },
{
// 汉字 “一” 同样无效
a: "",
b: "字符串",
c: "汉字"
},
{ c: 16 },
{
a: 16,
b: 64,
c: 16
}
];
const data2 = [{ a: "不知道" }, { a: "不知道" }, { a: "不知道" }];
const result1 = sumKeysInObjects(data1, ["a", "b", "c"]);
console.log(result1);
const result2 = sumKeysInObjects(data2, ["a", "b", "c"]);
console.log(result2);
键 "a" 有 2 个值被跳过(不存在或非有效数字)。
键 "b" 有 3 个值被跳过(不存在或非有效数字)。
键 "c" 有 3 个值被跳过(不存在或非有效数字)。
{ a: 80, b: 128, c: 32 }
键 "a" 在数组中没有有效数字,结果为 0。
键 "b" 在数组中没有有效数字,结果为 0。
键 "c" 在数组中没有有效数字,结果为 0。
{ a: 0, b: 0, c: 0 }