![](/img/trans.png)
[英]swift remove item from array after `filter` or by finding `firstIndex that `contains`
[英]Swift: String firstIndex after character
我正在尝试检测字符串上的括号,例如: foo(bar)baz(blim)
并反转括号内的内容,但我的实现超出了反弹范围:
func reverseInParentheses(inputString: String) -> String {
var tmpStr = inputString
var done = false
while !done {
if let lastIndexOfChar = tmpStr.lastIndex(of: "(") {
let startIndex = tmpStr.index(lastIndexOfChar, offsetBy:1)
if let index = tmpStr.firstIndex(of: ")") {
let range = startIndex..<index
let strToVerse = String(tmpStr[range])
let reversedStr = reverseStr(str: strToVerse)
tmpStr = tmpStr.replacingOccurrences(of: "(" + strToVerse + ")", with: reversedStr)
}
} else {
done = true
}
}
return tmpStr
}
我怎样才能在startIndex
之后获得tmpStr.firstIndex(of: ")")
你们中的任何人都知道如何做到这一点?
如何在
startIndex
之后获得tmpStr.firstIndex(of: ")")
?
一种方法是在startIndex
处“剪切”字符串,并获得下半部分。 然后在 substring 上使用firstIndex(of:)
。 由于Substring
只是原始字符串的“视图”,因此firstIndexOf
仍然返回原始字符串的索引。
let string = "foo(bar)baz(blim)"
if let lastIndexOfChar = string.lastIndex(of: "(") {
let startIndex = string.index(after: lastIndexOfChar)
let substring = string[startIndex..<string.endIndex] // cut off the first part of the string.
// now you have a "Substring" object
if let indexAfterOpenBracket = substring.firstIndex(of: ")") {
// prints "blim", showing that the index is indeed from the original string
print(string[startIndex..<indexAfterOpenBracket])
}
}
您可以将其编写为扩展:
extension StringProtocol {
func firstIndex(of char: Character, after index: Index) -> Index? {
let substring = self[index..<endIndex]
return substring.firstIndex(of: char)
}
}
现在,如果您在reverseInParentheses
中调用tmpStr.firstIndex(of: ")", after: startIndex)
,它应该可以工作。
您可以迭代保留索引作为参考的字符串,以将其与 endIndex 进行比较。 因此,每次您成功找到一个范围时,您都会在结束索引之后开始进行新的搜索。 顺便说一句,您不应该使用 replaceOccurrences,因为它也可能替换不在括号内的单词。 您可以使用 RangeReplaceableCollection replaceSubrange
并将反转的 substring 传递给该方法。
要查找字符之后的第一个索引,您可以扩展集合并返回元素的 firstIndex 之后的索引(如果找到):
extension Collection where Element: Equatable {
func firstIndex(after element: Element) -> Index? {
guard let index = firstIndex(of: element) else { return nil }
return self.index(after: index)
}
}
您的方法应如下所示:
func reverseInParentheses(inputString: String) -> String {
var inputString = inputString
var startIndex = inputString.startIndex
while startIndex < inputString.endIndex,
let start = inputString[startIndex...].firstIndex(after: "("),
let end = inputString[start...].firstIndex(of: ")") {
inputString.replaceSubrange(start..<end, with: inputString[start..<end].reversed())
startIndex = inputString.index(after: end)
}
return inputString
}
let str = "foo(bar)baz(blim)"
reverseInParentheses(inputString: str) // "foo(rab)baz(milb)"
或扩展StringProtocol
并将Self
约束到RangeReplaceableCollection
:
extension StringProtocol where Self: RangeReplaceableCollection {
var reversingSubstringsBetweenParentheses: Self {
var startIndex = self.startIndex
var source = self
while startIndex < endIndex,
let start = source[startIndex...].firstIndex(after: "("),
let end = source[start...].firstIndex(of: ")") {
source.replaceSubrange(start..<end, with: source[start..<end].reversed())
startIndex = index(after: end)
}
return source
}
}
let str = "foo(bar)baz(blim)"
str.reversingSubstringsBetweenParentheses // "foo(rab)baz(milb)"
更新了 Leo Dabus 的答案,以防在最后一个括号后写更多的文字。
func reverseInParentheses(_ str: String) -> String {
var str = str
var startIndex = str.startIndex
Var lastIndexOfChar = str.lastIndex(of: ")") ?? startIndex
while startIndex < lastIndexOfChar {
let start = str[startIndex...].firstIndex(after: "("),
let end = str[start...].firstIndex(of: ")") {
str.replaceSubrange(start..<end, with: str[start..<end].reversed())
startIndex = str.index(after: end)
}
return str
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.