如何确定字符串数组的最长公共前缀和后缀?

时间:2018-01-25 18:12:20

标签: ios swift

假设我有字符串数组:

["A12[1]", "A13[1]", "A14[1]"]

我需要找到最长的公共前缀A1和后缀[1]

其他例子:

["9-b", "10-b", "11-b"] - >后缀-b,没有前缀

["A12", "A14", "A6"] - >前缀A,没有后缀

如何遍历数组以查找字符串结束并启动数组中的每个字符串?

3 个答案:

答案 0 :(得分:4)

  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "clean-webpack-plugin": "^0.1.17",
    "css-loader": "^0.28.7",
    "eslint": "^4.10.0",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "install": "^0.10.1",
    "npm": "^5.5.1",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.19.0",
    "uglifyjs-webpack-plugin": "^1.1.4",
    "webpack": "^3.10.0",
    "webpack-dev-middleware": "^2.0.1",
    "webpack-hot-middleware": "^2.21.0"
  }
}

如果您要导入Foundation,可以使用其extension Collection where Element: StringProtocol { func longestCommonPrefix() -> String { guard var prefix = first.map({ String($0) }) else { return "" } for string in dropFirst() { while !string.hasPrefix(prefix) { prefix.removeLast() } } return prefix } func longestCommonSuffix() -> String { guard var suffix = first.map({ String($0) }) else { return "" } for string in dropFirst() { while !string.hasSuffix(suffix) { suffix.removeFirst() } } return suffix } } print(["A12[1]", "A13[1]", "A14[1]"].longestCommonPrefix()) // "A1" print(["A12[1]", "A13[1]", "A14[1]"].longestCommonSuffix()) // "[1]" print(["9-b", "10-b", "11-b"].longestCommonPrefix()) // "" print(["9-b", "10-b", "11-b"].longestCommonSuffix()) // "-b" print(["A12", "A14", "A6"].longestCommonPrefix()) // "A" print(["A12", "A14", "A6"].longestCommonSuffix()) // "" 扩展方法编写更短的版本:

String.commonPrefix(with:)

我从Martin R的回答中了解到import Foundation extension Collection where Element: StringProtocol { func longestCommonPrefix() -> String { guard let first = self.first.map({ String($0) }) else { return "" } return dropFirst().reduce(first, { $0.commonPrefix(with: $1) }) } func longestCommonSuffix() -> String { return String(self.lazy.map({ String($0.reversed()) }).longestCommonPrefix().reversed()) } }

答案 1 :(得分:3)

String已经有commonPrefix(with:)方法(如果导入了Foundation),所以一个简单的解决方案是在整个字符串数组中“折叠”:

import Foundation

func longestCommonPrefix(of strings: [String]) -> String {
    guard let first = strings.first else { return "" }
    return strings.dropFirst().reduce(first) { $0.commonPrefix(with: $1) }
}

基于Find the longest common starting substring in a set of strings中的想法,更有效的解决方案是

  • 查找数组中最小和最大的字符串。
  • 确定这两个字符串的公共前缀。

func longestCommonPrefix(of strings: [String]) -> String {

    guard let first = strings.first else { return "" }

    var (minString, maxString) = (first, first)
    for str in strings.dropFirst() {
        if str < minString { minString = str }
        else if str > maxString { maxString = str }
    }

    return minString.commonPrefix(with: maxString)
}

说明:

  • 空输入数组可被视为致命错误。
  • 可以使用min()max()代替循环,但是 需要两次遍历字符串而不是一次。

然后可以将最长的公共后缀计算为(反向) 反向字符串的最长公共前缀:

func longestCommonSuffix(of strings: [String]) -> String {
    let revStrings = strings.map { String($0.reversed()) }
    let revPrefix = longestCommonPrefix(of: revStrings)
    return String(revPrefix.reversed())
}

示例:

print(longestCommonPrefix(of: ["A12[1]", "A13[1]", "A14[1]"])) // "A1"
print(longestCommonSuffix(of: ["A12[1]", "A13[1]", "A14[1]"])) // "[1]"

print(longestCommonPrefix(of: ["9-b", "10-b", "11-b"])) // ""
print(longestCommonSuffix(of: ["9-b", "10-b", "11-b"])) // "-b"

答案 2 :(得分:1)

也许问题只是想象一个人如何询问阵列的所有成员是否相等?

extension Collection where Element : Equatable {
    var allEqual : Bool {
        let orig = self.first
        for elem in self {
            if elem != orig {
                return false
            }
        }
        return true
    }
}

一旦你有了这个,你可以尝试从数组中最短字符串的长度开始减少长度的前缀:

func commonPrefix(_ arr:[String]) -> String {
    let prefixmax = arr.map {Int($0.count)}.min()!
    var prefix = ""
    for i in (1...prefixmax).reversed() {
        let prefixes = arr.map {$0.prefix(i)}
        if prefixes.allEqual {
            prefix = String(prefixes[0])
            break
        }
    }
    return prefix
}

let arr = ["A12[1]", "A13[1]", "A14[1]"]
let pref = commonPrefix(arr) // "A1"

对后缀执行相同的操作留给读者练习。