Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flatten all values of multiple arrays in Swift

Tags:

arrays

swift

I have a Dictionary of Integer Arrays like below:

let numbers = [1: [2, 3], 4: [5, 6, 7], 8: [9]]

What I really want is a single flattened Array of all of the values (which themselves are arrays), like so:

[2, 3, 5, 6, 7, 9]

Now, I have been able to call numbers.values.array to get:

[[2, 3], [5, 6, 7], [9]]

But what I'm looking for is to merge these one step further, flattening them.

Does Swift (1.1, or 1.2) offer a convenience method for this?

like image 476
tyler Avatar asked Apr 24 '15 04:04

tyler


People also ask

Is flatMap deprecated Swift?

So Swift cannot use this flatMap method. Here, transform must return an Optional of a single output element. Since Swift can implicitly promote any non-optional value to an optional value, Swift can use this version of flatMap to compile your code. The deprecated flatMap was deprecated by SE-0187.

How do I use compactMap in Swift?

The compactMap(_:) function automatically removes nil elements from the returned array, after calling map(_:) on it. As such, it's return type is non-optional. In the above code, the type of result is [Int].


2 Answers

With a combination of numbers.values.array and a reduce function you can simplify this down in one line of code.

numbers.values.array.reduce([], combine: +) // [5,6,7,2,3,9]

However, I would like to note that since you are using a dictionary, you cannot guarantee that the values will be sorted, so you can use the sorted function to accomplish this:

sorted(numbers.values.array.reduce([], combine: +), <) // [2,3,5,6,7,9]

As @Jeffery Thomas stated, you can also use flatmap which was just added in Swift 1.2:

sorted(numbers.values.array.flatMap { $0 }, <)

And to take it a step further, using the global sorted function, the < is extraneous because it is the default and using the global reduce and flatMap functions, you can remove the array property as pointed out by Martin R, so it can be reduced down to:

sorted(reduce(numbers.values, [], +))
sorted(flatMap(numbers.values) { $0 })
like image 142
Ian Avatar answered Oct 30 '22 23:10

Ian


Another possible solution is

[].join(numbers.values)

And if you want the values in the order corresponding to the sorted dictionary keys then it would be

flatMap(sorted(numbers.keys)) { numbers[$0]! }
like image 43
Martin R Avatar answered Oct 30 '22 23:10

Martin R