Harry Pray
Harry Pray

Reputation: 25

Using an array of Booleans to select specific indices for transformation

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

Answers (1)

Martin R
Martin R

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

Related Questions