9

If I have an object that is declared as

let compoundArray = [Array<String>]

is there a property that would give me the number of strings in all the arrays contained in compoundArray?

I can do it by adding up all the items in each array within:

var totalCount = 0
for array in compoundArray {
   totalCount += array.count }
//totalCount = total items in all arrays within compoundArray

But that seems clunky and it seems that swift would have a property/method of Array to do this, no?

Thanks!

shallowThought
  • 19,212
  • 9
  • 65
  • 112
Jonathan Tuzman
  • 11,568
  • 18
  • 69
  • 129

3 Answers3

18

You can add the nested array counts with

let count = compoundArray.reduce(0) { $0 + $1.count }

Performance comparison for large arrays (compiled and run on a MacBook Pro in Release configuration):

let N = 20_000
let compoundArray = Array(repeating: Array(repeating: "String", count: N), count: N)

do {
    let start = Date()
    let count = compoundArray.joined().count
    let end = Date()
    print(end.timeIntervalSince(start))
    // 0.729196012020111
}

do {
    let start = Date()
    let count = compoundArray.flatMap({$0}).count
    let end = Date()
    print(end.timeIntervalSince(start))
    // 29.841913998127
}

do {
    let start = Date()
    let count = compoundArray.reduce(0) { $0 + $1.count }
    let end = Date()
    print(end.timeIntervalSince(start))
    // 0.000432014465332031
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
12

You can use joined or flatMap for that.

Using joined

let count = compoundArray.joined().count

Using flatMap

let count = compoundArray.flatMap({$0}).count
Nirav D
  • 71,513
  • 12
  • 161
  • 183
  • why when i create array in this way var arr = Array(count: 3, repeatedValue: Array(count: 2, repeatedValue: "String")) count of the elements is wrong with flatMap approach ? – Oleg Gordiichuk Jan 13 '17 at 10:09
  • 1
    @OlegGordiichuk that is not valid Swift 3 syntax. For `var arr = Array(repeating: Array(repeating: "String", count: 2), count: 3)` we correctly get a total count of 6 using the `flatMap` approach. – dfrib Jan 13 '17 at 10:12
  • 1
    @NiravD my bad I look at the count of the iterations not in the actual result. Number of iteration was 4 but count is 6 – Oleg Gordiichuk Jan 13 '17 at 10:16
  • @OlegGordiichuk It's ok :) – Nirav D Jan 13 '17 at 10:17
  • 6
    Of these two methods, `joined` might be preferable because it returns a "view" on the flattened collection, whereas `flatMap` creates a new array. – Martin R Jan 13 '17 at 10:32
  • @MartinR Thanks for the suggestion :) – Nirav D Jan 13 '17 at 10:40
3

Since you are asking for a property, I thought I'd point out how to create one (for all collections, while we're at it):

extension Collection where Iterator.Element: Collection {
    var flatCount: Int {
        return self.reduce(0) { $0 + $1.count } // as per Martin R
    }
}

Making this recursive seems to be an interesting exercise.

Raphael
  • 9,779
  • 5
  • 63
  • 94