Oscar Apeland Oscar Apeland - 11 months ago 36
Swift Question

Filter array based on next object

I'm writing some code to filter out driving trips from the motion sensor. I figured out the best way to do this is to add a subarray to a nested array based on the following:

  • Detect the first occurrence of a confident automotive event

  • Add all the following motion events to the same array of the events until the first confident observation that says otherwise.

For example

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.

Currently i'm doing it this way:

//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
} else {
if !needsNew {
//If user is no longer in car, store a cpoy of the session and reset the array
automotiveActivitySession = []
needsNew = true

This solution is not very elegant.
Is there any way to use Swift's
to make this sorting prettier?


Filter is not going to do it, but you can use reduce.

The example below shows how to collect runs of consecutive "A"s (denoting an automotive event) into arrays inside an array of arrays:

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" {
    return current

The prior value is passed to reduce's function as the first parameter. This makes it possible for the function to decide whether to append to the current list or to start a new list.

The result of this run is as follows:

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