TypeScript中使用Lodash合并多数组并对元素执行自定义计算
lodash/fp 按年份跨对象计算数值实现方案
你当前处理的是Record<string, number[][]>结构的多份数据集,需要按相同key下的匹配年份,对多份输入的数值执行自定义算术规则,示例规则为同一年份结果 = input1值 + input2值 - input3值,预期输出2002年结果25、2003年结果60。
你已经实现了单key下的数值提取,得到按输入分组的数值矩阵:
map(a => a.map(nth(1)))(map('key1')([input1, input2, input3])) // 返回值 [[10, 50], [20, 70], [5, 60]]
之前使用zip/zipWith未得到预期结果,核心原因是没有做矩阵转置:你拿到的矩阵第一维度是输入来源,第二维度是年份,需要先把维度互换,把同一年份的所有输入值归为一组,再执行计算。
具体实现
基础版:匹配当前示例需求
核心分三步:提取数值矩阵、转置矩阵按年份分组、执行自定义计算
import { map, nth, zip } from 'lodash/fp'; const inputs = [input1, input2, input3]; // 1. 提取key1下所有年份的纯数值,得到按输入分组的矩阵 const valueMatrix = map(item => item.key1.map(nth(1)))(inputs); // 2. 转置矩阵,得到按年份分组的数值集合:[[10,20,5], [50,70,60]] const yearValueGroups = zip(...valueMatrix); // 3. 按规则计算每个年份的结果 const result = map(([val1, val2, val3]) => val1 + val2 - val3)(yearValueGroups); // 输出 [25, 60],和预期完全一致
如果需要保留年份和值的映射关系,只需要在提取阶段保留年份字段即可:
// 提取key1下的原始[年份, 值]对 const rawEntryMatrix = map('key1')(inputs); // 转置后按年份分组 const yearGroups = zip(...rawEntryMatrix); // 计算时保留年份标识 const resultWithYear = map(group => { const year = group[0][0]; const calcVal = group[0][1] + group[1][1] - group[2][1]; return [year, calcVal]; })(yearGroups); // 输出 [[2002, 25], [2003, 60]]
通用封装版
可以把逻辑封装为可复用函数,支持任意数量输入、任意key、任意计算规则:
import { map, nth, zip } from 'lodash/fp'; /** * 按年份跨输入数据集计算数值 * @param {Array} inputList 所有输入数据组成的数组 * @param {string} targetKey 要计算的key名 * @param {Function} calcFn 计算回调,入参为同一年份所有输入的数值组成的数组 * @returns {Array} [年份, 计算结果] 组成的二维数组 */ const calcAcrossInputs = (inputList, targetKey, calcFn) => { const entryMatrix = map(item => item[targetKey])(inputList); const yearGroups = zip(...entryMatrix); return map(group => { const currentYear = group[0][0]; const yearValues = map(nth(1))(group); return [currentYear, calcFn(yearValues)]; })(yearGroups); }; // 调用示例 const finalResult = calcAcrossInputs( [input1, input2, input3], 'key1', ([v1, v2, v3]) => v1 + v2 - v3 );
之前zipWith未生效的原因
zipWith本身完全可以实现这个需求,之前没拿到正确结果,大概率是没有正确传入展开后的矩阵和对应计算回调,正确写法如下:
import { zipWith } from 'lodash/fp'; // 一行完成转置+计算 const quickResult = zipWith((...values) => values[0] + values[1] - values[2])(...valueMatrix); // 输出 [25, 60]
内容的提问来源于stack exchange,提问作者alik
相关产品推荐
相关产品推荐

