appzYourLife appzYourLife - 4 months ago 15
Swift Question

Splitting an Array into Sub-Arrays in Swift

Problem



Given an array of values how can I split it into
sub-arrays
made of elements that are equals?

Example



Given this array

let numbers = [1, 1, 1, 3, 3, 4]


I want this output

[[1,1,1], [3, 3], [4]]


What I am NOT looking for



A possible way of solving this would be creating some sort of index to indicate the occurrences of each element like this.

let indexes = [1:3, 3:2, 4:1]


And finally use the index to rebuild the output array.

let subsequences = indexes.sort { $0.0.0 < $0.1.0 }.reduce([Int]()) { (res, elm) -> [Int] in
return res + [Int](count: elm.1, repeatedValue: elm.0)
}


However with this solution I am losing the original values. Of course in this case it's not a big problem (an
Int
value is still and
Int
even if recreated) but I would like to apply this solution to more complex data structures like this

struct Starship: Equatable {
let name: String
let warpSpeed: Int
}

func ==(left:Starship, right:Starship) -> Bool {
return left.warpSpeed == right.warpSpeed
}


Final considerations



The function I am looking for would be some kind of reverse of
flatten()
, infact

let subsequences: [[Int]] = [[1,1,1], [3, 3], [4]]
print(Array(subsequences.flatten())) // [1, 1, 1, 3, 3, 4]


I hope I made myself clear, let me know should you need further details.

Answer
 // extract unique numbers using a set, then
 // map sub-arrays of the original arrays with a filter on each distinct number

 let numbers = [1, 1, 1, 3, 3, 4]

 let numberGroups = Set(numbers).map{ value in return numbers.filter{$0==value} }

 print(numberGroups)

[EDIT] changed to use Set Initializer as suggested by Hamish