1

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
0

3 Answers 3

2

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
Sign up to request clarification or add additional context in comments.

Comments

2

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) }

2 Comments

How exactly do I add a 0? let count = fooArray.reduce(0) { $0 + $1.bars?.count ?? 0}
@Tarek sorry. I forgot for (). See edit: { $0 + ($1.bars?.count ?? 0) }
1

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 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.