0

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?

4
  • I'm not a swift programmer, but have you tried: numbers[2][1] = 7; Commented Aug 29, 2017 at 17:53
  • 1
    @TheUnholyProgrammer the nested array can vary in size, so you could have [[2, 12, 14], [5], [6]], where index 3 refers to the 5. Commented Aug 29, 2017 at 17:56
  • try using numbers[2].length; Commented Aug 29, 2017 at 17:57
  • @XmasRights I think your problem is desperately calling for a new data type that more smartly manages the operations this [[Int]] supports Commented Sep 11, 2017 at 16:49

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

-1

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]]

2 Comments

In the OP's question, they want to replace 3 with 42, not append 42 to the array
Also this will cause a fatal error if the index is too high

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.