2D array lookup in swift - similar to vlookup in excel

时间:2019-03-17 22:45:56

标签: arrays swift vlookup

Re:

Finding a value in an array of arrays (similar to VLOOKUP function in Excel) in Swift

The above shows a method for determining the next lowest value in a 2D array given a search value. Reproduced here for convenience:

let testArray: [[Double]] = [
        [0,0],
        [1000,20.5],
        [3000,21],
        [3500,22.5],
        [3300,21],
]

let income: Double = 3500

var closest = testArray[0][0]
var closestDif = closest - income

for innerArray in testArray {
    let value = innerArray[0]

    let thisDif = value - income

    guard thisDif <= 0 else {
        continue
    }

    if closestDif < thisDif {
        closestDif = thisDif
        closest = value

        guard closestDif != 0 else {
            break
        }
    }
}

print(closest)

The value returned for closest is 3500. Can someone please describe how we then retrieve the corresponding second number in the array [3500, 22.5] i.e. 22.5?

(edit) Is enumerated(){....} a cleaner way to do this?

Thanks!

2 个答案:

答案 0 :(得分:0)

You can easily modify Martin R's answer from the linked Q&A to keep the whole inner array in compactMap and then find the maximum based on the first element of each inner array.

let result = testArray.compactMap { $0[0] <= income ? $0 : nil }.max(by: {$0.first! < $1.first!})! // [3500, 22.5]

答案 1 :(得分:0)

@David Pasztor谢谢您的解决方案效果很好。我正在使用swift 3,因此我不得不用“ flatMap”代替“ compactMap”,但否则效果很好,只需一行代码!我使用相同的技术还获得了数据中与搜索值(收入)最接近的较高值,然后进行插值以在第二列中获得与搜索值收入成比例的值。当搜索值收入等于第一列中的一个值时,内插法需要防止被零除。在这种情况下,相应的result0 [0],[1]和result1 [0],[1]相同。

let testarray:[[Double]] = [
    [0,0],
    [1000,20.5],
    [3000,21],
    [3500,22.5],
    [3300,21],
]

let income:Double = 3400
let result0 = testarray.flatMap { $0[0] <= income ? $0 : nil }.max(by: {$0.first! < $1.first!})!
let result1 = testarray.flatMap { $0[0] >= income ? $0 : nil }.min(by: {$0.first! < $1.first!})!

if income - result0[0] < 0.001 {
    let interp = result0[1]
    print(interp)
}
else {
    let interp = result0[1] + (result1[1] - result0[1])*(income -  result0[0])/(result1[0] - result0[0])
    print(interp)   // 21.75
}