Reputation: 823
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
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
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
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