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
有没有有效的方法找出数组中哪个对象最接近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
保存为变量。
然后迭代数组。每次比较数组中值的差异与最小差异。
如果新的差异较小,则换出最小差异。
在数组的末尾,您将得到最小差异。
这与查找最大值、最小值等相同...
为完成起见,我将post解决此问题的最终代码
//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([=10=], ) })
//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: { [=10=] >= givenValue })!
let under = sorted.last(where: { [=10=] <= 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,即使给定值不在范围内,它也会 return 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
语句并且看起来很干净。我不喜欢 return 值是 nil
;但是,我尽量避免 throwing
错误,并且 returning 给定值是不准确的。
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
}
}
}
假设我有一个数组
var values:[CGFloat] = [-12.0, 450, 300]
我需要找出这些数字中哪个最接近给定值,比如
var givenValue:CGFloat = 64
有没有有效的方法找出数组中哪个对象最接近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
保存为变量。
然后迭代数组。每次比较数组中值的差异与最小差异。
如果新的差异较小,则换出最小差异。
在数组的末尾,您将得到最小差异。
这与查找最大值、最小值等相同...
为完成起见,我将post解决此问题的最终代码
//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([=10=], ) })
//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: { [=10=] >= givenValue })!
let under = sorted.last(where: { [=10=] <= 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,即使给定值不在范围内,它也会 return 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
语句并且看起来很干净。我不喜欢 return 值是 nil
;但是,我尽量避免 throwing
错误,并且 returning 给定值是不准确的。
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
}
}
}