2

Let's say I have this array of strings:

let Vehicles = ["Aeroplane", "Bicycle", "CarVehicle", "Lorry", "Motorbike", "Scooter", "Ship", "Train"]

What I want is this result:

let resultArray = [["Aeroplane", "Bicycle", "CarVehicle", "Lorry"], ["Motorbike", "Scooter", "Ship", "Train"]]

I know I could do this by for but I want to use Higher Order functions in Swift. I mean functions like map, reduce, filter. I think it's possible to do this way and it could be better. Can anyone help me with this? Thanks

Libor Zapletal
  • 13,752
  • 20
  • 95
  • 182
  • See [my answer](http://stackoverflow.com/a/33540708/1966109) to a very similar question that offers up to 5 different ways to solve your problem. – Imanou Petit Mar 09 '17 at 23:58

1 Answers1

5

A possible solution with map() and stride():

let vehicles = ["Aeroplane", "Bicycle", "CarVehicle", "Lorry", "Motorbike", "Scooter", "Ship", "Train"]
let each = 4

let resultArray = map(stride(from: 0, to: vehicles.count, by: each)) {
    vehicles[$0 ..< advance($0, each, vehicles.count)]
}

println(resultArray)
// [[Aeroplane, Bicycle, CarVehicle, Lorry], [Motorbike, Scooter, Ship, Train]]

The usage of advance() in the closure guarantees that the code works even if the number of array elements is not a multiple of 4 (and the last subarray in the result will then be shorter.)

You can simplify it to

let resultArray = map(stride(from: 0, to: vehicles.count, by: each)) {
    vehicles[$0 ..< $0 + each]
}

if you know that the number of array elements is a multiple of 4.

Strictly speaking the elements of resultArray are not arrays but array slices. In many cases that does not matter, otherwise you can replace it by

let resultArray = map(stride(from: 0, to: vehicles.count, by: each)) {
    Array(vehicles[$0 ..< advance($0, each, vehicles.count)])
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Looks like what I was looking for. I forget mention that number of elements don't need to be multiple of 4 so thanks for first solution. One more thing. I have problem that I have result as `ArraySlice` not `[String]`. How can I fix it? – Libor Zapletal May 13 '15 at 17:29
  • @MartinR Would it also be possible to do it with `reduce` and `map` together? – Eendje May 13 '15 at 17:31
  • @JacobsonTalom: It would be possible with `reduce()`, but then a "nested array" would be created in each call of the reduce closure, so that is probably less effective. Of course there might be another solution that I did not think of. – Martin R May 13 '15 at 17:36