JavaScript实现类似C# LINQ的数组去重与筛选需求
在JavaScript中筛选Date唯一且保留TimeEdit最新条目的最佳实现方式
我来给你梳理下在JavaScript里实现这个需求的最佳方式~
首先看你要处理的原数组:
var arr = [{ TimeEdit: "2020-10-29T10:45:00.21Z", Date: "2020-10-29T00:00:00", Parameters: [ { Id: 1, Value: 1}, { Id: 2, Value: 348 }] },{ TimeEdit: "2020-10-29T10:43:52.22Z", Date: "2020-10-29T00:00:00", Parameters: [ { Id: 1, Value: 12}, { Id: 2, Value: 348 }] },{ TimeEdit: "2020-10-30T10:47:12.33Z", Date: "2020-10-30T00:00:00", Parameters: [ { Id: 1, Value: 3}, { Id: 2, Value: 2 }] }];
你的需求是筛选出Date字段唯一的项,且每个Date保留TimeEdit最新的条目,期望输出如下:
[{ TimeEdit: "2020-10-29T10:45:00.21Z", Date: "2020-10-29T00:00:00", Parameters: [ { Id: 1, Value: 1}, { Id: 2, Value: 348 }] },{ TimeEdit: "2020-10-30T10:47:12.33Z", Date: "2020-10-30T00:00:00", Parameters: [ { Id: 1, Value: 3}, { Id: 2, Value: 2 }] }];
你提到在C#里可以先取去重的Date再循环筛选,在JavaScript里,最高效的方式是利用映射结构(普通对象或Map),只需要遍历一次数组就能完成,时间复杂度为O(n),比多次遍历的方式性能好很多,尤其是数组规模大的时候。
方式一:用普通对象做映射(简单直观)
const dateMap = {}; arr.forEach(item => { const dateKey = item.Date; // 如果当前日期未记录,或当前条目的TimeEdit比已存的更新 if (!dateMap[dateKey] || new Date(item.TimeEdit) > new Date(dateMap[dateKey].TimeEdit)) { dateMap[dateKey] = item; } }); // 把对象的值转为数组就是最终结果 const result = Object.values(dateMap);
方式二:用Map结构(更规范的键值对存储)
如果你更倾向于ES6的规范数据结构,可以用Map来实现,逻辑和上面一致:
const dateMap = new Map(); arr.forEach(item => { const currentDate = item.Date; const existingItem = dateMap.get(currentDate); if (!existingItem || new Date(item.TimeEdit) > new Date(existingItem.TimeEdit)) { dateMap.set(currentDate, item); } }); // 将Map的值转为数组 const result = Array.from(dateMap.values());
方式三:链式调用风格(用reduce实现)
如果你习惯函数式编程的链式写法,也可以用reduce来完成,本质还是映射的思路:
const result = Object.values(arr.reduce((map, item) => { const date = item.Date; if (!map[date] || new Date(item.TimeEdit) > new Date(map[date].TimeEdit)) { map[date] = item; } return map; }, {}));
为什么推荐这类方式?
这种方法只需要遍历原数组一次,相比先去重Date再循环查找的方式(会遍历多次数组),性能优势明显。而且逻辑清晰,每一步都直接处理当前条目,判断是否需要更新对应Date的最新记录。
内容的提问来源于stack exchange,提问作者MrSends
相关产品推荐
相关产品推荐

