Reputation: 25
I am trying to use an array of Booleans as a mechanism for transforming specific indices in another identically sized array of Ints while ignoring the indices that contain a false in the corresponding selection array.
Basically, I want this function to only transform the values that contain a 'true' in the corresponding boolean selection array and leave the others as they already are.
Here's how I managed to (sort of) get it to work using a for loop.
However, I'd like to know how to do this in a more functional style. I'm also open to being told that this is absolutely foolish and I should try another way. I had some success using a zip function to create a tuple at each recursion but I'd like to see how experts do it.
I'd like to see if it is possible using a map instead of an ugly for loop like I did here.
func changeSelectedChannels(_ newVal: UInt8, forChannels selections: [Bool], array oldArray: [UInt8]) -> [UInt8] {
var j = 0
var newArray = oldArray
for index in selections{
if index == true{
newArray[j] = newVal
j += 1
}else{
j += 1
}
}
return newArray
}
Upvotes: 1
Views: 124
Reputation: 540005
You can achieve the same result with zip()
and map()
:
func changeSelectedChannels(_ newVal: UInt8, forChannels selections: [Bool], array oldArray: [UInt8]) -> [UInt8] {
let newArray = zip(oldArray, selections).map {
(oldVal, flag) in flag ? newVal : oldVal
}
return newArray
}
The closure is called with all pairs (one element from oldArray
and the corresponding element from selections
), and returns either the old array value or newVal
.
Another possible solution is to use enumerated()
to get rid of the j
index variable:
func changeSelectedChannels(_ newVal: UInt8, forChannels selections: [Bool], array oldArray: [UInt8]) -> [UInt8] {
var newArray = oldArray
for (idx, flag) in selections.enumerated() where flag {
newArray[idx] = newVal
}
return newArray
}
Upvotes: 1