Reputation: 721
I may have this really wrong. Noob. I've recreated what I'm doing in a playground type environment here. Basically the sender is a slider within a UITableView of other sliders. The myData is the underlying data. I want to perform a calculation to all the items of the underlying data EXCEPT the one which corresponds to the sender item. I have no idea if my closure syntax is correct. This is the first time I'm creating one.
// sender comes over as a struct
struct myStruct {
var tag: Int = 0
var value: Float = 0
}
let sender = myStruct(tag: 1, value: 199)
// some vars for the calculation
let globalTotal: Float = 597
let globalAnotherTotal: Float = 0
// an array of data structs
struct myDataStruct {
var name: String = ""
var value: Float = 0
}
var myData: [myDataStruct] = []
myData.append(myDataStruct(name: "Tom", value: 45.0))
myData.append(myDataStruct(name: "Dick", value: 16.4))
myData.append(myDataStruct(name: "Harry", value: 12.3))
// a closure to do the calculation
var calcOtherVals: (Float, Float) -> (Float) = { (startVal, senderStartVal) in
let remainingStartVals = globalTotal - senderStartVal
let remainingNewVal = globalTotal - sender.value - globalAnotherTotal
let endVal = ((startVal * (100 / remainingStartVals)) / 100) * remainingNewVal
return endVal
}
// now need to perform calcOtherVals on all the .value floats in myData EXCEPT the element at position sender.tag hopefully using filter and map
So basically I'm trying to use filter and map and the calcOtherVals closure to edit the array of structs in place. I can do this with conditionals and loops and calcOtherVals as a function no problem. Just hoping to do it more elegantly.
QUESTION: As in the code comment, I need to perform calcOtherVals
on all the .value floats in myData EXCEPT the element at position sender.tag
. How?
Upvotes: 1
Views: 6306
Reputation: 1355
This Question is Already have an answer,
for better understanding you can review this very good tutorial about map, filter and reduce
Link:- https://useyourloaf.com/blog/swift-guide-to-map-filter-reduce/
Upvotes: -1
Reputation: 1509
myData.enumerated().flatMap { (index, element) in return index != sender.tag ? calcOtherVals (element.value) : nil }
Few bits of swift magic here. Firstly enumerate()
returns an array of tuples containing the element, and the index of said element.
Next flatMap()
. This is essentially map
but it ignores any transform that resolves to nil. Great for converting from an optional array to a flat array, and also great if you wish to do a map+filter operation such as this.
-- Updated --
If you're comfortable with implicit arguments, you can reduce it further:
myData.enumerated().flatMap { $0.offset != sender.tag ? calcOtherVals ($0.element.value) : nil }
Upvotes: 5
Reputation: 442
So as I understood you need to filter your array something like
let filteredData = myData.filter({$0.tag != sender.tag})
then you use reduce to calculate
let sumAll = filterdData.reduce(0, {$0.value + $1.value})
Upvotes: 3