字典不会开箱即用,它只会为您提供精确的键匹配。
但是,由于它是一个集合,如果给定一个距离函数,您可以编写一个搜索可用的最接近匹配的函数。这是一个通用函数:
(注意我没有花太多时间调试这个,谨慎使用!:)
/// Search any collection for the index of the closest match, given a
/// function to compute the distance between the elements and the target.
///
/// Returns nil in case of an empty collection.
func findClosestMatchTo<Col: CollectionType, Target, Distance: Comparable>
(target: Target, within col: Col, #byDistance: (Target,Col.Generator.Element)->Distance) -> Col.Index?
{
var match: Col.Index? = nil
var bestDistanceSoFar: Distance? = nil
for (idx,elem) in zip(indices(col),col) {
let thisDistance = byDistance(target, elem)
if bestDistanceSoFar == nil || thisDistance < bestDistanceSoFar {
match = idx
bestDistanceSoFar = thisDistance
}
}
return match
}
/// A convenience version for Strideable types, that can always have their distance computed
func findClosestMatchTo
<Col: CollectionType where Col.Generator.Element: Strideable>
(target: Col.Generator.Element, within col: Col) -> Col.Index?
{
return findClosestMatchTo(target, within: col) { abs($0 - $1) }
}
// prints 1 (index of 20)
println(findClosestMatchTo(100, within: [1,20,700,9]))
// prints 2 (index of 700)
println(findClosestMatchTo(1000, within: [1,20,700,9]))
现在,您只需编写距离函数,以便比较键/值对的关键部分:
let dict: [CGFloat: String] = [1: "waffle", 5.6: "blabla", 32.4: "bla"]
let closest = findClosestMatchTo(5.5, within: dict) { abs($0 - $1.0) }
if let idx = closest {
dict[idx] // prints (5.6, “blabla”)
}
当然,这个算法相对于字典的大小是 O(n),所以如果你发现自己不断地搜索匹配但很少插入或查找键,你可能想看看不同的数据结构或算法(可能是树或排序数组 + 二分查找)。