5

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?

Tyler
  • 19,113
  • 19
  • 94
  • 151

3 Answers3

7

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 })
Ian
  • 12,538
  • 5
  • 43
  • 62
6

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]! }
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Although it is ambiguous, I would assume that you want to sort the final value array, not sort the dictionary keys. So sorted(flatMap(numbers.keys){numbers[$0]!}) Never mind, I see your comment above. – Price Ringo Apr 24 '15 at 05:03
5

This is called flattening, and it's a relatively common operation. There are a number of ways to do it, so pick one that suits your needs.

numbers.values.array.reduce([], combine: +) // As stated by @Bluehound
reduce(numbers.values, [], +)
numbers.values.array.flatMap { $0 } // Swift 1.2 (Xcode 6.3)
flatMap(numbers.values) { $0 } // Swift 1.2 (Xcode 6.3)

flatMap may be the most useful, if the next step after flattening is mapping.

NOTE: Thanks @MartinR for the syntax tip.

Community
  • 1
  • 1
Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117