假设我有字符串数组:
["A12[1]", "A13[1]", "A14[1]"]
我需要找到最长的公共前缀A1
和后缀[1]
。
其他例子:
["9-b", "10-b", "11-b"]
- >后缀-b
,没有前缀
["A12", "A14", "A6"]
- >前缀A
,没有后缀
如何遍历数组以查找字符串结束并启动数组中的每个字符串?
答案 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"
对后缀执行相同的操作留给读者练习。