[英]Get the most closest value of the CGFloat
I am curious if there is a way in swift to achieve the most closest value via their modern api's?我很好奇是否有一种方法可以通过他们的现代 api 快速实现最接近的价值?
For example:例如:
let x = [1.2, 3.4, 4.5, 6.7, 8.9]
print(x.getClosestValue(3.7) //3.4
I have been playing around with map and reduce but still not be able to crack this problem.我一直在玩地图和减少但仍然无法解决这个问题。 The problem occur's that I have to iterate through entire array to detect false positives as well.出现的问题是我必须遍历整个数组以检测误报。 There can be a scenario where you can have multiple closest values, so was just wondering how this can be done in swiftly way?在某些情况下,您可以拥有多个最接近的值,所以只是想知道如何快速完成?
You can use min(by:)
to achieve this and it doesn't require a sorted array您可以使用min(by:)
来实现这一点,它不需要排序数组
let x = [1.2, 3.4, 4.5, 6.7, 8.9]
let target = 3.7
let closestTarget = x.min(by: {abs($0 - target) < abs($1 - target)})
I can imagine some different scenarios, so I will try to address most of them.我可以想象一些不同的场景,所以我将尝试解决其中的大部分问题。
You can use min(by:)
:您可以使用min(by:)
:
let x = [1.2, 4.0, 3.4, 6.7, 8.9]
let target = 3.7
let closestValue = x.min { abs($0 - target) < abs($1 - target) }
print(closestValue) // prints Optional(4.0)
This approach is the most straightforward.这种方法是最直接的。 You will get the result that returns the minimum value of the subtraction between the array element and the target.您将得到返回数组元素与目标之间相减的最小值的结果。
You can also use min(by:)
, but first, you get the enumerated version of the array to get the indices.您也可以使用min(by:)
,但首先,您可以获得数组的枚举版本以获取索引。
let x = [1.2, 4.0, 3.4, 6.7, 8.9]
let target = 3.7
let closestIdx = x.enumerated().min { abs($0.1 - target) < abs($1.1 - target) }!.0
print(closestIdx) // prints 1
Note: Even though 3.4 is equally distant to 3.7 as 4.0, this approach will always return 4.0 as the answer because of floating-point arithmetic (you can check this blog post if you're interested in this topic).注意:尽管 3.4 与 3.7 的距离与 4.0 相同,但由于浮点运算,此方法将始终返回 4.0 作为答案(如果您对此主题感兴趣,可以查看此博客文章)。
Since you've mentioned that there can be multiple numbers, I think this would be the method of your choice.既然您提到可以有多个数字,我认为这将是您选择的方法。
let x = [1.2, 3.4, 4.0, 6.7, 8.9]
let target = 3.7
let minDiff = x.map { return abs($0 - target) }.min()!
let closestValues = x.filter { isDoubleEqual(a: $0, b: target - minDiff) || isDoubleEqual(a: $0, b: target + minDiff) }
print(closestValues) // prints [3.4, 4.0]
The difference here is that we use filter()
to find all the values that are equally distant to a target.这里的区别在于我们使用filter()
来查找与目标等距的所有值。 There may be repeated values, which can be eliminated using a Set if you wish.可能存在重复值,如果您愿意,可以使用 Set 消除这些值。
The same idea of using enumerated()
again to take the indices.再次使用enumerated()
获取索引的相同想法。
let x = [1.2, 3.4, 4.0, 6.7, 8.9]
let target = 3.7
let minDiff = x.map { return abs($0 - target) }.min()!
let tuples = x.enumerated().filter { isDoubleEqual(a: $0.1, b: target - minDiff) || isDoubleEqual(a: $0.1, b: target + minDiff) }
let closestIndices = tuples.map { return $0.0 }
print(closestIndices) // prints [1, 2]
Note: isDoubleEqual(a: Double, b: Double) -> Bool
is a function that returns true
if the values a
and b
are considered equal according to floating-point arithmetic.注意: isDoubleEqual(a: Double, b: Double) -> Bool
是一个函数,如果根据浮点算法认为值a
和b
相等,则返回true
。 See this post for more information - but note that you should adjust the epsilon to a value that you find suitable.有关更多信息,请参阅此帖子- 但请注意,您应该将 epsilon 调整为您认为合适的值。
The complexity of these solutions is O(n).这些解决方案的复杂度是 O(n)。
A final note: if you have an array that is already sorted, as mentioned by other answers, you can take advantage of this property to find what you want using a binary search.最后一点:如果您有一个已经排序的数组,如其他答案所述,您可以利用此属性使用二分搜索找到您想要的内容。
This solution using reduce(_:_:)
should work:这个使用reduce(_:_:)
解决方案应该可以工作:
let x = [1.2, 3.4, 4.5, 6.7, 8.9]
let target = 4.7
// assumes x is non-empty array
let closestTarget = x.reduce(x[0]) { closest,val in
abs(target - closest) > abs(target - val) ? val : closest
}
There is no straight api from Apple to use yet.目前还没有来自 Apple 的直接 API 可供使用。 If you don't care about the time, you can sort the array and use Array's first(where:)
or last(where:)
methods to do linear search.如果你不关心时间,你可以对数组进行排序,并使用 Array 的first(where:)
或last(where:)
方法进行线性搜索。 However, you can make it better by sort and using binary search, it will probably just take you additional 20 lines?但是,您可以通过排序和使用二分搜索使其更好,它可能只需要额外的 20 行?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.