如何用Lodash实现TypeScript中C# LINQ GroupBy+Select等效逻辑?
我太懂你这种卡了好几个小时找不到解决办法的憋屈了!你要实现的C#代码逻辑,本质上是按IdShopItem分组后确保每个分组只有唯一元素,然后取出这个元素——毕竟C#里的Single()如果碰到分组里有多个元素可是会直接抛异常的。
不用纠结那些有bug的LinQ库,给你几个靠谱的TypeScript实现方式,无依赖或者正确用Lodash都可以:
方法1:原生数组+Map实现(最推荐,无外部依赖)
直接用原生数组的reduce方法结合Map,既能实现去重,还能完全匹配C#Single()的严格校验逻辑(重复ID就抛错):
// 先定义你的数据类型(根据实际情况调整) interface ShopItem { IdShopItem: number; name?: string; // 其他属性... } function getUniqueShopItems(items: ShopItem[]): ShopItem[] { const itemMap = items.reduce((acc, currentItem) => { // 校验是否存在重复ID,和C# Single()行为一致 if (acc.has(currentItem.IdShopItem)) { throw new Error(`发现重复的IdShopItem: ${currentItem.IdShopItem}`); } acc.set(currentItem.IdShopItem, currentItem); return acc; }, new Map<number, ShopItem>()); // 把Map的值转为数组返回 return Array.from(itemMap.values()); }
如果你的场景允许忽略重复(只保留第一个出现的项),直接去掉throw那行代码就行。
方法2:Lodash的正确用法(如果你偏好使用Lodash)
你之前用Lodash的groupBy没成功,大概率是没对分组后的结果做处理。其实Lodash有现成的uniqBy方法,完美匹配你的需求:
import _ from 'lodash'; // 宽松模式:保留每个IdShopItem对应的第一个项 function getUniqueShopItemsLodash(items: ShopItem[]): ShopItem[] { return _.uniqBy(items, 'IdShopItem'); } // 严格模式:和C# Single()一致,重复ID抛错 function getUniqueShopItemsLodashStrict(items: ShopItem[]): ShopItem[] { const grouped = _.groupBy(items, 'IdShopItem'); return Object.values(grouped).map(group => { if (group.length !== 1) { throw new Error(`IdShopItem ${group[0].IdShopItem}对应${group.length}个元素,不符合唯一要求`); } return group[0]; }); }
uniqBy方法直接帮你按指定键去重,比手动用groupBy再处理简洁太多,之前可能没注意到这个方法~
方法3:原生数组filter+Set(链式写法)
如果你更喜欢链式调用的风格,可以用filter结合Set来实现:
function getUniqueShopItemsFilter(items: ShopItem[]): ShopItem[] { const seenIds = new Set<number>(); return items.filter(item => { if (seenIds.has(item.IdShopItem)) { // 严格校验:重复ID抛错 throw new Error(`重复的IdShopItem: ${item.IdShopItem}`); // 宽松模式:直接跳过重复项,注释上面的throw,打开下面的return false // return false; } seenIds.add(item.IdShopItem); return true; }); }
这个方法会保留原数组中元素的顺序,同时实现去重或严格校验。
内容的提问来源于stack exchange,提问作者Gerald Hughes
相关产品推荐
相关产品推荐

