簡體   English   中英

Swift:檢查 NSArray 中的哪個值最接近另一個給定值

[英]Swift: Check which value in NSArray is closest to another given value

可以說我有一個數組

var values:[CGFloat] = [-12.0, 450, 300]

我需要找出這些數字中哪個最接近給定值,比如

var givenValue:CGFloat = 64

有沒有一種有效的方法來找出數組中哪個 object 最接近 64?
我知道你可以這樣做:

if abs(values[0] - 64) < abs(values[1] - 64) && abs(values[0] - 64) < abs(values[2] - 64) {
    println("values[0] is the closest to 64)
}

但這將導致多個 if 語句並且看起來效率低下。

有誰知道更好的方法嗎? 在這個例子中,我需要數組中的值以及它在數組中的哪個 objectIndex。

minimumDifference保存為變量。

然后迭代數組。 每次將數組中值的差異與最小差異進行比較。

如果新的差異較小,則換出最小差異。

在數組的末尾,您將獲得最小的差異。

這與查找最大值、最小值等相同...

為了完成起見,我將發布解決此問題的最終代碼

    //Array to hold dist. of visible cell to pt. 64
    var distancesToTop = [CGFloat]()

    //Array of visible cell indexPaths
    var indexPaths = tableView.indexPathsForVisibleRows()!

    for visibleCell in tableView.visibleCells() { //for each visible cell...

        //Append distance to 64 to the array
        distancesToTop.append(abs((visibleCell.frame.minY - tableView.contentOffset.y) - 64))

    }

    //Find the lowest of those values
    let numMin = distancesToTop.reduce(CGFloat.max, { min($0, $1) })

    //Determine the objectForIndexPath that the minimum number was in
    let num = find(distancesToTop, numMin)!

Swift 4.2 中,這可以使用數組first(where:)last(where:)方法來完成。 請注意,下面的示例代碼對可選值不安全,如果givenValue超出values數組的范圍,則會失敗。

    func findClosest(_ values: [CGFloat], _ givenValue: CGFloat) -> CGFloat {

        let sorted = values.sorted()

        let over = sorted.first(where: { $0 >= givenValue })!
        let under = sorted.last(where: { $0 <= givenValue })!

        let diffOver = over - givenValue
        let diffUnder = givenValue - under

        return (diffOver < diffUnder) ? over : under
    }

    let values:[CGFloat] = [-12.0, 450, 300]

    print(findClosest(values, 64.0))   // -12.0
    print(findClosest(values, 143.0))  // -12.0
    print(findClosest(values, 144.5))  // 300

您可以使用元組來保存最近的值和距離。 此代碼將最接近的值設置為 0,即使給定的值不在該范圍內,它也會返回 0。如果您願意,可以將該值設為可選值,然后將其包裝起來。

 func findClosest(_ values: [CGFloat], _ givenValue: CGFloat) -> CGFloat {
    var result: (nearest: CGFloat, distance: CGFloat) = (0, .greatestFiniteMagnitude)
    
    for point in values.sorted(){
        let distance = abs(point - givenValue)
        if result.distance > distance {
            result = (nearest: point, distance: distance)
        }
    }
    return result.nearest
}

您還可以使用AdditiveArithmetic使函數對數字更通用。

我會在數組上使用 reduce 來找到最接近的值。 這將只需要一個if-else語句並且看起來很干凈。 我不喜歡返回值為nil 但是,我盡量避免throwing錯誤並避免返回給定值不准確。

var values: [CGFloat] = [100, 150, 200]

let pivot: CGFloat = 120

let closest = getClosestValue(to: pivot, from: values) /// 100

func getClosestValue(to pivot: CGFloat, from values: [CGFloat]) -> CGFloat? {
    guard let firstValue = values.first else { return nil }
  
    return values.reduce(firstValue) { partialResult, nextValue in
        let partial = abs(pivot - partialResult)
        let next = abs(pivot - nextValue)
    
        if partial > next {
            return nextValue
        } else {
            return partialResult
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM