Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using nested reduce in Swift

I have an array which contains an arrays of Double, like in the screenshot:

enter image description here

My goal is to get the sum of the multiplication of the Double elements of each array. It means, I want to multiply all elements of each array then, in my case, I will have 3 values so I get the sum of them.

I want to use reduce, flatMap ? or any elegant solution.

What I have tried ?

totalCombinations.reduce(0.0) { $0 + ($1[0]*$1[1]*$1[2])  }

but this work only when I know the size of the arrays that contains the doubles.

like image 402
iOSGeek Avatar asked Jul 28 '16 10:07

iOSGeek


People also ask

What is the use of reduce in Swift?

Use the reduce(_:_:) method to produce a single value from the elements of an entire sequence. For example, you can use this method on an array of numbers to find their sum or product.

How do I use compactMap in Swift?

The compactMap(_:) function automatically removes nil elements from the returned array, after calling map(_:) on it. As such, it's return type is non-optional. In the above code, the type of result is [Int].

What does map function do in Swift?

The map() Function in Swift. In Swift, you can use the built-in map() function to modify each element in a collection. The map() function loops through the collection, applying a function for each element. The map() function always returns an array where the transformed values are.


2 Answers

Given these values

let lists: [[Double]] = [[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]]

let's take a look at several possible approaches

Solution #1

let sum =  lists.reduce(0) { $0 + $1.reduce(1, combine: *) }

Solution #2

If you define this extension

extension SequenceType where Generator.Element == Double {
    var product : Double { return reduce(1.0, combine: *) }
}

then you can write

let sum = lists.reduce(0) { $0 + $1.product }

Solution #3

With the extension defined above you can also write

let sum = lists.map { $0.product }.reduce(0, combine:+)

Solution #4

If we define these 2 postfix operators

postfix operator +>{}
postfix func +>(values:[Double]) -> Double {
    return values.reduce(0, combine: +)
}

postfix operator *>{}
postfix func *>(values:[Double]) -> Double {
    return values.reduce(1, combine: *)
}

we can write

lists.map(*>)+>
like image 63
Luca Angeletti Avatar answered Sep 22 '22 09:09

Luca Angeletti


You can write something like this:

let totalCombinations: [[Double]] = [
    [2.4,1.45,3.35],
    [2.4,1.45,1.42],
    [2.4,3.35,1.42],
    [1.45,3.35,1.42],
]

let result = totalCombinations.reduce(0.0) {$0 + $1.reduce(1.0) {$0 * $1} }

print(result) //->34.91405

But I'm not sure it's "elegant" or not.

like image 33
OOPer Avatar answered Sep 19 '22 09:09

OOPer