【问题标题】:Closest-match string-array sorting in SwiftSwift 中的最接近匹配字符串数组排序
【发布时间】:2017-12-13 13:53:02
【问题描述】:

使用 Swift4,我想根据与给定 searchTerm 最接近的匹配对字符串数组进行排序。对我来说重要的是,如果可以找到完全匹配的 searchTerm,那么 returnArray 应该预先显示这个 searchTerm!

示例:给定Array = ["Hello world", "Hello Jamaica", "Hello", "Family", "Hel"]

searchTerm = "Hello",算法应该返回:

["Hello", "Hello world", "Hello Jamaica", "Hel", "Family"].

方法一: 我尝试使用FuzzyMatching - 它以某种方式工作(即它确实根据给定的searchTerm对inputArray进行了排序,但是它并没有将精确匹配放在前面!即使用FuzzyMatching我实现了根据子字符串匹配的良好排序和语法排序。但它并没有在 returnArray 中为我带来完全匹配)。

方法 2: 然后我尝试了我自己的算法——(见下面的代码)。但是如果数组中有几个字符串都以我的 searchTerm 开头(即以 searchTerm 作为前缀),那么不知何故我的算法做得不好。

static func bestMatchFilterdStringArray(inputArray: [String], searchTerm: String) -> [String] {

    let matchingTerms = inputArray
        .filter { $0.range(of: searchTerm, options: .caseInsensitive) != nil }
        .sorted { ($0.hasPrefix(searchTerm) ? 0 : 1) < ($1.hasPrefix(searchTerm) ? 0 : 1) }
    return matchingTerms
}

在 Swift4 中如何进行“最接近匹配的字符串数组排序”?尤其是在 returnArray 中提前为我带来完全匹配?任何帮助表示赞赏!

【问题讨论】:

标签: arrays swift sorting match closest


【解决方案1】:

您可以使用Levenshtein distance score 将您的搜索词与数组中的每个字符串进行比较,得分最高的将是结果数组中的第一个词,等等。您的结果将是一个按顺序排序的字符串数组降序分数的顺序。

以下对字符串的扩展可用于获取 Levenshtein 距离分数。在该算法中,值越高,相等性越好

 extension String {
    func levenshteinDistanceScore(to string: String, ignoreCase: Bool = true, trimWhiteSpacesAndNewLines: Bool = true) -> Double {

        var firstString = self
        var secondString = string

        if ignoreCase {
            firstString = firstString.lowercased()
            secondString = secondString.lowercased()
        }
        if trimWhiteSpacesAndNewLines {
            firstString = firstString.trimmingCharacters(in: .whitespacesAndNewlines)
            secondString = secondString.trimmingCharacters(in: .whitespacesAndNewlines)
        }

        let empty = [Int](repeating:0, count: secondString.count)
        var last = [Int](0...secondString.count)

        for (i, tLett) in firstString.enumerated() {
            var cur = [i + 1] + empty
            for (j, sLett) in secondString.enumerated() {
                cur[j + 1] = tLett == sLett ? last[j] : Swift.min(last[j], last[j + 1], cur[j])+1
            }
            last = cur
        }

        // maximum string length between the two
        let lowestScore = max(firstString.count, secondString.count)

        if let validDistance = last.last {
            return  1 - (Double(validDistance) / Double(lowestScore))
        }

        return 0.0
    }
}

【讨论】:

  • 谢谢你,Ankit,......因为我已经有一段时间没有问这个问题了,所以我需要先深入了解一下。再次感谢您的解决方案!
猜你喜欢
  • 2017-03-29
  • 2011-08-17
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多