Swift如何移除数组中与前序元素时间戳间隔6小时内的对象
需求说明
你需要对携带时间戳的Entry对象数组做过滤,移除所有与上一个保留元素时间戳间隔小于6小时的对象,最终得到按6小时窗口精简的数组。
示例效果:
输入:[Obj(00:00), Obj(04:00), Obj(06:01), Obj(07:00), Obj(12:00)]
输出:[Obj(00:00), Obj(06:01), Obj(12:00)]
涉及的对象结构体定义:
struct Entry { var intensity: Float? var timestamp: Date? }
实现步骤
- 预处理数组:先过滤掉
timestamp为nil的无效对象,避免时间计算出错,再按时间戳从小到大做升序排序,保证遍历顺序和时间线一致 - 初始化结果数组,将排序后的第一个有效元素加入结果,同时记录这个元素的时间戳作为第一个参考时间
- 从第二个元素开始遍历数组,逐个计算当前元素时间戳和上一个保留元素时间戳的差值
- 如果时间差值达到6小时间隔阈值,就将当前元素加入结果数组,同时更新参考时间为当前元素的时间戳;如果差值小于6小时,直接跳过该元素
可直接使用的代码
func filterSixHourChunkEntries(_ entries: [Entry]) -> [Entry] { // 过滤空时间戳对象 + 时间升序排序 let validSortedList = entries .filter { $0.timestamp != nil } .sorted { $0.timestamp! < $1.timestamp! } // 无有效数据直接返回空 guard let firstEntry = validSortedList.first, let firstTimestamp = firstEntry.timestamp else { return [] } var filteredResult: [Entry] = [firstEntry] var lastKeptTime = firstTimestamp // 6小时对应的秒数 let gapThreshold: TimeInterval = 6 * 60 * 60 // 从第二个元素开始遍历判断 for entry in validSortedList.dropFirst() { guard let currentTime = entry.timestamp else { continue } let timeGap = currentTime.timeIntervalSince(lastKeptTime) if timeGap >= gapThreshold { filteredResult.append(entry) lastKeptTime = currentTime } } return filteredResult }
补充说明
- 示例中
06:01到12:00的时间差为5小时59分,严格来说不满足6小时间隔,如果需要和示例输出完全匹配,可以把判断条件的>=调整为>,或者根据业务需求微调阈值即可 - 如果需要保留
timestamp为nil的对象,可以自行调整预处理逻辑,比如将nil时间对象统一放在结果数组头部/尾部,不参与间隔计算 - 如果业务涉及跨时区、夏令时等特殊时间场景,建议使用
Calendar的dateComponents(_:from:to:)方法计算小时差,替代直接的秒数差值计算,避免时间误差
内容的提问来源于stack exchange,提问作者FrontFacingWindowCleaner
相关产品推荐
相关产品推荐

