XmasRights
XmasRights

Reputation: 1509

Modifying Nested Array Entries in Swift

I have a nested array in Swift, where each internal array could be of varying size:

let numbers = [[0], [1], [2, 3], [4]]

The problem is that I need to modify one entry based on a single index value (based essentially on the index of the flattened array; so in this example, each value is essentially its index).

I've got half the problem down with a flatMap call, but I'm not sure how to re-nest it afterwards, or whether I've taken the wrong approach in the first place.

func setValue(_ value: Int, index: Int, list: [[Int]]) -> [[Int]]
{
    var output = numbers.flatMap { $0 }
    output[index] = value

    // TODO: Re-nest

    return [output]
}

let output = setValue(42, index: 3, list: numbers)
print(output) // [[0, 1, 2, 42, 4]]

How do I make this output [[0], [1], [2, 42], [4]], and is there a more elegant (functional) way to achieve this?

Upvotes: 0

Views: 719

Answers (3)

Brandon Mowat
Brandon Mowat

Reputation: 374

I have a (somewhat) functional solution using two maps.

func setValue(_ value: Int, index: Int, list: [[Int]]) -> [[Int]] {
    var i = -1
    return list.map { arr in
        return arr.map { e in
            i += 1
            if (i == index) { return value }
            else { return e }
        }
    }
}

I haven't had a lot of time to think about a clever way to solve this problem, but this is my hacky one.

Upvotes: 1

Santosh
Santosh

Reputation: 2914

Try this and let me know if it works for you.

var numbers = [[0], [1], [2, 3], [4]]
func setValue(_ value: Int, index: Int, list: inout [[Int]]) {
    var listS: [Int] = list[index]
    listS.append(value)
    list[index] = listS    
}

setValue(42, index: 2, list: &numbers)
print(numbers) // [[0], [1], [2, 3, 42], [4]]

Upvotes: -1

Code Different
Code Different

Reputation: 93181

Keep iterating through the subarrays until you have reached the specified index, then calculate its offset within that subarray:

func setValue(_ value: Int, index: Int, list: [[Int]]) -> [[Int]]
{
    var output = list
    var cumulativeCount = 0

    for i in 0..<output.count {
        if cumulativeCount + output[i].count > index {
            output[i][index - cumulativeCount] = value
            break
        } else {
            cumulativeCount += output[i].count
        }
    }

    return output
}

print(setValue(42, index: 3, list: [[0], [1], [2, 3], [4]]))
print(setValue(42, index: 3, list:  [[2, 12, 14], [5], [6]]))

This however, does not check that index falls within the range of list. if you set index = 100 in this example, the function will not change anything.

Code Snippet on IBM Bluemix

Upvotes: 1

Related Questions