基于下一个对象过滤数组

时间:2016-05-01 19:30:44

标签: arrays swift

我正在编写一些代码来过滤掉运动传感器的驾驶行程。我想出最好的方法是根据以下内容将一个子数组添加到嵌套数组中:

  • 检测首次出现自信的汽车事件
  • 将所有以下动作事件添加到相同的事件数组中,直到第一次自信的观察结果为止。

例如

automotive confidence 2 //Add
automotive confidence 2 //Add
automotive confidence 2 //Add
walking confidence 2 //Add the sub-array to the master array and start over on the next confident automotive event. 

目前我这样做:

        //Remove all uncertain values.
        let confidentActivities = activities!.filter{$0.confidence.rawValue == 2}

        var needsNew = true
        var automotiveActivities:Array<Array<CMMotionActivity>> = Array() //Master array to contain subarrays of automotiveactivity arrays
        var automotiveActivitySession:Array<CMMotionActivity> = Array()
        for activity in confidentActivities {
            if activity.automotive && (!activity.cycling && !activity.running && !activity.walking){
                if needsNew {
                    needsNew = false
                }
                automotiveActivitySession.append(activity)
            } else {
                if !needsNew {
                    //If user is no longer in car, store a cpoy of the session and reset the array
                    automotiveActivities.append(Array(automotiveActivitySession))
                    automotiveActivitySession = []
                    needsNew = true
                }
            }
        }

这个解决方案不是很优雅。 有没有办法使用Swift的Array.filter{}来使这个排序更漂亮?

2 个答案:

答案 0 :(得分:1)

过滤器不会这样做,但您可以使用reduce

下面的示例显示了如何将连续"A"(表示汽车事件)的运行收集到数组数组中的数组中:

let data = ["A","A","A","B","A","A","B","A","A","A","A","B","B","B","A","B","A","A","A","A","A","A","B","A"]
var res = [[String]]()
_ = data.reduce("") { (last: String, current: String) in
    if current == "A" {
        if last != "A" {
            res.append([String]())
        }
        res[res.count-1].append(current)
    }
    return current
}
print(res)

先前的值作为第一个参数传递给reduce的函数。这使得函数可以决定是附加到当前列表还是开始新列表。

此次运行的结果如下:

[   ["A", "A", "A"]
,   ["A", "A"]
,   ["A", "A", "A", "A"]
,   ["A"]
,   ["A", "A", "A", "A", "A", "A"]
,   ["A"]]

答案 1 :(得分:0)

如果你正在使用漂亮的解决方案,可以使用split来执行此操作。您只需要为它提供一个应该被视为分隔符的条件。在您的情况下,这将是任何非汽车运动事件。

let arr = ["A","A","A","B","A","A","B","A","A","C","A","B","D","B","A","B","A","E","A","A","F","A","B","A","B"]
let split = arr.split {$0 != "A"} // insert your condition for whether the given element should be considered a 'seperator'

$0这里是数组中元素的匿名闭包参数(因为它迭代)。你总是可以扩展闭包,以使namings更明确,虽然看起来不那么优雅。例如:

let split = arr.split {element in
    return element != "A"
}

这将返回一个ArraySlices数组,如下所示:

[
    ArraySlice(["A", "A", "A"]),
    ArraySlice(["A", "A"]),
    ArraySlice(["A", "A"]),
    ArraySlice(["A"]),
    ArraySlice(["A"]),
    ArraySlice(["A"]),
    ArraySlice(["A", "A"]),
    ArraySlice(["A"]),
    ArraySlice(["A"])
]

如果您希望它们明确Arrays,您可以随后使用map

let split = arr.split {$0 != "A"}.map{Array($0)}

返回:

[
    ["A", "A", "A"],
    ["A", "A"],
    ["A", "A"],
    ["A"], ["A"],
    ["A"],
    ["A", "A"],
    ["A"],
    ["A"]
]