我正在写一些代码来过滤来自运动传感器的驾驶行程。我发现最好的方法是基于以下内容将子数组添加到嵌套数组中:
- 检测首次发生的自信汽车事件
- 将以下所有运动事件添加到相同的事件数组中,直到第一个确信的观察结果表明情况并非如此
例如
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{}
使这种排序更漂亮吗?
Filter不会这么做,但您可以使用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"]]
如果您想要一个漂亮的解决方案,您可以使用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
是数组中某个元素的匿名闭包参数(当它遍历时)。为了使命名更加明确,您可以始终扩展闭包,尽管它看起来不那么优雅。例如:
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"]
]