如何用TypeScript实现类似C# ToLookup的分组字典功能
问题:将对象数组按非唯一属性分组为字典的简便实现方式
我有一个包含specCode属性的类,该属性并非唯一键。当我拥有此类对象的数组时,希望将其转换为以specCode为键、对应所有同specCode对象数组为值的字典。目前我通过手动循环实现,代码如下:
const skusBySpecCode: { [key: string]: Sku[] } = {} for (const sku of x.skus) { if (!skusBySpecCode.hasOwnProperty(sku.specCode)) skusBySpecCode[sku.specCode] = [] skusBySpecCode[sku.specCode].push(sku) }
请问是否有更简便的实现方式?在C#中我会这样实现:
theArray .ToLookup(x => x.SpecCode) .ToDictionary(x => x.Key, x => x.ToArray());
回答
在TypeScript/JavaScript里,你可以用数组的reduce方法简化实现,代码更紧凑且逻辑清晰:
const skusBySpecCode = x.skus.reduce<{ [key: string]: Sku[] }>((acc, sku) => { // 初始化对应键的数组(如果不存在),再推入当前元素 acc[sku.specCode] ??= []; acc[sku.specCode].push(sku); return acc; }, {});
细节说明
reduce会遍历数组,将每个元素逐步累加到累加器对象(acc)中??=是空值合并赋值运算符(ES2021及以上支持),可以自动处理数组的初始化,替代手动判断hasOwnProperty的逻辑- 若需要兼容旧环境,可替换为
acc[sku.specCode] = acc[sku.specCode] || [],再执行push操作
如果偏好类似C#的链式调用风格,也可以封装一个通用的分组工具函数,模拟ToLookup的行为:
function groupBy<T, K extends string | number | symbol>( array: T[], keySelector: (item: T) => K ): Record<K, T[]> { return array.reduce((acc, item) => { const key = keySelector(item); acc[key] ??= []; acc[key].push(item); return acc; }, {} as Record<K, T[]>); } // 调用方式 const skusBySpecCode = groupBy(x.skus, sku => sku.specCode);
这样调用起来就和你熟悉的C#写法风格一致了。
内容的提问来源于stack exchange,提问作者Gargoyle
相关产品推荐
相关产品推荐

