2016-05-01 3 views
2

Я пишу код, чтобы отфильтровать поездки от датчика движения. Я понял, что лучший способ сделать это, чтобы добавить подмассив в гнездовой массив на основе следующий:Фильтр-массив на основе следующего объекта

  • Detect первого появление уверенного автомобильного события
  • Добавить все следующие события движения к тому же массив событий до первого уверенного наблюдения, в котором говорится иначе.

Например

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's Array.filter{}, чтобы сделать сортировку более красивой?

ответ

1

Фильтр не намерен это делать, но вы можете использовать reduce.

В приведенном ниже примере показано, как собрать пробеги последовательных "A" S (обозначающий автомобильное событие) в массивы внутри массив массивов:

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 «s как первый параметр. Это позволяет функции решить, добавлять ли к текущему списку или запускать новый список.

В результате этого запуска выглядит следующим образом:

[ ["A", "A", "A"] 
, ["A", "A"] 
, ["A", "A", "A", "A"] 
, ["A"] 
, ["A", "A", "A", "A", "A", "A"] 
, ["A"]] 
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 здесь является анонимным закрытие аргумент для элемента в массиве (как это перебирает). Вы всегда можете расширить закрытие, чтобы сделать более понятными имена, хотя выглядит менее элегантно. Например:

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"] 
] 
Смежные вопросы