Tarek
Tarek

Reputation: 823

Swift - Getting the count of all arrays in an array of custom object

I have an array of custom object "Foo".

Each "Foo" has an optional array of "Bar".

I know I could do it using for loops but I'm hoping for a more elegant way, possibly using flatMap, filter and/or reduce.

Foo can have more properties of different types.

class Foo {
   var bars: [Bar]?
}

let foo1 = Foo()
let foo2 = Foo()
let foo3 = Foo()

let bar1 = Bar()
let bar2 = Bar()
let bar3 = Bar()

foo1.bars.append(bar2)
foo1.bars.append(bar3)

foo2.bars.append(bar1)
foo2.bars.append(bar2)
foo2.bars.append(bar3)

foo3.bars.append(bar1)
foo3.bars.append(bar2)

let FooArray = [Foo1, Foo2, Foo3]
// Magic -> Print 7

Upvotes: 1

Views: 537

Answers (3)

Robert Dresler
Robert Dresler

Reputation: 11150

First, I would suggest you to make your Foo model struct instead and initalize empty Array instead of declaring optional array

struct Bar {}

struct Foo {
    var bars = [Bar]()
}

Then you can use reduce. Add number of elements inside bars array of each Foo to sum.

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

var foo1 = Foo()
var foo2 = Foo()
var foo3 = Foo()

foo1.bars = [Bar(),Bar()]
foo2.bars = [Bar(),Bar(),Bar()]
foo3.bars = [Bar(),Bar()]

let fooArray = [foo1, foo2, foo3]
let count = fooArray.reduce(0) { $0 + $1.bars.count }
print(count) // 7

If you want to keep type of bars as optional array, you can just add 0 to sum

let count = fooArray.reduce(0) { $0 + ($1.bars?.count ?? 0) }

Upvotes: 2

AamirR
AamirR

Reputation: 12198

You can use Array.reduce

let count = FooArray.reduce(0) { $0 + ($1.bars?.count ?? 0) }

Paste this in playground

class Bar {

}
class Foo {
    var bars: [Bar]?

    func appendBar(_ bar: Bar) {
        if self.bars == nil {
            self.bars = [bar]
        } else {
            self.bars!.append(bar)
        }
    }
}

let foo1 = Foo()
let foo2 = Foo()
let foo3 = Foo()

let bar1 = Bar()
let bar2 = Bar()
let bar3 = Bar()

foo1.appendBar(bar2)
foo1.appendBar(bar3)

foo2.appendBar(bar1)
foo2.appendBar(bar2)
foo2.appendBar(bar3)

foo3.appendBar(bar1)
foo3.appendBar(bar2)

let FooArray = [foo1, foo2, foo3]
let count = FooArray.reduce(0) { $0 + ($1.bars?.count ?? 0) }
print(count) // Output: 7

Upvotes: 2

idmean
idmean

Reputation: 14875

There is no need to change Foo as Robert Dresler suggests. This will work just fine:

let count = fooArray.reduce(0) { $0 + $1.bars?.count ?? 0 }

Upvotes: 1

Related Questions