【问题标题】:Filter an array by time interval按时间间隔过滤数组
【发布时间】:2017-09-01 22:59:18
【问题描述】:

在我的应用中,我每 20 毫秒记录一次从设备的加速度计获取的加速度数据。我有一个恰当地命名为AccelerationData 的类来存储这些值。我还以毫秒为单位记录每个读数的时间戳。

class AccelerationData {
    var timestamp: Int64 = 0 // in milliseconds
    var x: Double = 0.0
    var y: Double = 0.0
    var z: Double = 0.0

    var timestampDate: Date {
        return Date(milliseconds: timestamp)
    }

    var JSONDictionary: [String: Any] {
        let jsonDictionary: [String: Any] = [
            "X": x,
            "Y": y,
            "Z": z,
            "TIME": timestamp
        ]
        return jsonDictionary
    }
}

extension Date {

    var milliseconds: Int64 {
        return Int64(self.timeIntervalSince1970 * 1000)
    }

    init(milliseconds: Int64) {
        self = Date(timeIntervalSince1970: TimeInterval(milliseconds / 1000))
    }

}

录制结束后,我需要为所有这些读数创建一个 JSON 正文。我不想获取所有这些读数,而是想通过每 500 毫秒(0.5 秒)发生的读数来过滤它。

根据我的研究我found,您可以将flatMap 用于这样的任务,但是当涉及时间戳等动态值时,我不确定如何应用它。

如果您能提供一些关于如何开始的指导,我将不胜感激。

【问题讨论】:

  • 请注意,Date(timeIntervalSince1970:) 的时间间隔以 秒为单位, 而不是毫秒。
  • @MartinR 哦,是的!我实际上有一个单独的扩展方法来做到这一点。我忘记更新类中的属性。更新了我的代码。
  • 按“每 500 毫秒”读数过滤?如果读数之间间隔 2 秒会发生什么?

标签: ios arrays swift filtering


【解决方案1】:

我会为此目的使用一个简单的 for 循环。 假设数据按时间戳排序,可能如下所示:

let measurements: [AccelerationData] = ... // your full array of acceleration data
var reducedMeasurements = [AccelerationData]()

var nextTimeStamp = measurements.first!.timestamp // Assuming that the array is not empty
for accData in measurements {
    if accData.timestamp >= nextTimeStamp {
        reducedMeasurements.append(accData)
        nextTimeStamp += 500 // add 0.5 seconds
    }
}

如果你“坚持”使用过滤器,这里有一个可能的解决方案:

func timeFilter(delta: Int64) -> (Int64) -> Bool {
    var nextTimeStamp: Int64?
    return { timeStamp in
        if let next = nextTimeStamp {
            if timeStamp >= next {
                nextTimeStamp = next + delta
                return true
            } else {
                return false
            }
        } else {
            // First call:
            nextTimeStamp = timeStamp + delta
            return true
        }
    }
}

let measurements: [AccelerationData] = ...
let filter = timeFilter(delta: 500)
let reducedMeasurements = measurements.filter { filter($0.timestamp) }

timeFilter(delta: 500) 创建一个使用捕获的闭包 变量以跟踪下一个时间戳。代码大概可以 被简化,但希望能证明这个想法。

【讨论】:

  • nextTimeStamp 是一个日期,不是nextTimeStamp += 0.5 吗?
  • @Guig:OP 将属性定义为var timestamp: Int64 = 0 // in milliseconds
  • @MartinR - 您需要在 timeFilter() 函数中进行小修改...第一次使用 timeStamp >= nextTimeStamp,需要使用 if nextTimeStamp == Int64.min { nextTimeStamp = timeStamp } 更新 nextTimeStamp ...否则,您只是每次将Int64.min 递增 500...
  • @DonMag:确实!这再次表明应该使用可选项而不是“魔术常量”。希望现在是正确的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-05
  • 2011-12-20
  • 2021-05-07
  • 1970-01-01
  • 2010-09-24
  • 2011-02-08
  • 2019-06-28
相关资源
最近更新 更多