What is the most succinct way to remove the first character from a string in Swift?
我想从字符串中删除第一个字符。 到目前为止,我想出的最简洁的方法是:
1 | display.text = display.text!.substringFromIndex(advance(display.text!.startIndex, 1)) |
我知道由于Unicode我们无法使用
如果您使用的是Swift 3,则可以忽略此答案的第二部分。好消息是,这实际上现在又很简洁!仅使用String的新remove(at :)方法。
1 2 3 4 | var myString ="Hello, World" myString.remove(at: myString.startIndex) myString //"ello, World" |
我喜欢全局
1 2 | let original ="Hello" // Hello let sliced = dropFirst(original) // ello |
它简短,清晰,适用于符合Sliceable协议的任何内容。
如果您使用的是Swift 2,则此答案已更改。您仍然可以使用dropFirst,但不能不从字符串
1 2 | let original ="Hello" // Hello let sliced = String(original.characters.dropFirst()) // ello |
另一种选择是使用后缀函数来拼接字符串的
1 2 | let original ="Hello" // Hello let sliced = String(suffix(original.utf16, original.utf16.count - 1)) // ello |
这就是说,我最初提供的解决方案并不是在较新版本的Swift中做到这一点的最简洁的方法。如果您正在寻找一个简短而直观的解决方案,我建议您使用
1 2 3 4 | var original ="Hello" // Hello let removedChar = original.removeAtIndex(original.startIndex) original // ello |
正如@vacawama在下面的注释中所指出的,不修改原始String的另一个选项是使用substringFromIndex。
1 2 | let original ="Hello" // Hello let substring = original.substringFromIndex(advance(original.startIndex, 1)) // ello |
或者,如果您恰巧希望将某个字符从String的开头和结尾删除,则可以使用substringWithRange。只要确保
1 2 3 4 5 6 | let original ="Hello" // Hello let newStartIndex = advance(original.startIndex, 1) let newEndIndex = advance(original.endIndex, -1) let substring = original.substringWithRange(newStartIndex..<newEndIndex) // ell |
最后一行也可以使用下标符号书写。
1 | let substring = original[newStartIndex..<newEndIndex] |
Swift 4更新
在Swift 4中,
1 2 3 | let str ="hello" let result1 = String(str.dropFirst()) //"ello" let result2 = String(str.dropLast()) //"hell" |
1 2 | let result3 = String(str.dropLast(3)) //"he" let result4 = String(str.dropFirst(4)) //"o" |
如果指定要删除的字符多于字符串中的字符,则结果将是空字符串(
1 | let result5 = String(str.dropFirst(10)) //"" |
Swift 3更新
如果您只想删除第一个字符并想要更改原始字符串,请参阅@ MickMacCallum的答案。如果要在此过程中创建新字符串,请使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | extension String { func chopPrefix(_ count: Int = 1) -> String { return substring(from: index(startIndex, offsetBy: count)) } func chopSuffix(_ count: Int = 1) -> String { return substring(to: index(endIndex, offsetBy: -count)) } } "hello".chopPrefix() //"ello" "hello".chopPrefix(3) //"lo" "hello".chopSuffix() //"hell" "hello".chopSuffix(3) //"he" |
像之前的
斯威夫特2.x
不幸的是,在Swift 2中,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | extension String { func chopPrefix(count: Int = 1) -> String { return self.substringFromIndex(advance(self.startIndex, count)) } func chopSuffix(count: Int = 1) -> String { return self.substringToIndex(advance(self.endIndex, -count)) } } "hello".chopPrefix() //"ello" "hello".chopPrefix(3) //"lo" "hello".chopSuffix() //"hell" "hello".chopSuffix(3) //"he" |
像之前的
在Swift 1.2中,您需要像这样调用
1 | "hello".chopPrefix(count: 3) //"lo" |
或者您可以在函数定义中添加下划线
1 2 3 4 5 6 7 8 9 | extension String { func chopPrefix(_ count: Int = 1) -> String { return self.substringFromIndex(advance(self.startIndex, count)) } func chopSuffix(_ count: Int = 1) -> String { return self.substringToIndex(advance(self.endIndex, -count)) } } |
斯威夫特2.2
'advance' is unavailable: call the 'advancedBy(n)' method on the index
1 2 3 4 5 6 7 | func chopPrefix(count: Int = 1) -> String { return self.substringFromIndex(self.startIndex.advancedBy(count)) } func chopSuffix(count: Int = 1) -> String { return self.substringFromIndex(self.endIndex.advancedBy(count)) } |
斯威夫特3.0
1 2 3 4 5 6 7 | func chopPrefix(_ count: Int = 1) -> String { return self.substring(from: self.characters.index(self.startIndex, offsetBy: count)) } func chopSuffix(_ count: Int = 1) -> String { return self.substring(to: self.characters.index(self.endIndex, offsetBy: -count)) } |
斯威夫特3.2
A view of the string's contents as a collection of characters.
1
2 @available(swift, deprecated: 3.2, message:"Please use String or Substring directly")
public var characters: String.CharacterView
1 2 3 4 5 6 7 8 9 10 11 12 13 | func chopPrefix(_ count: Int = 1) -> String { if count >= 0 && count <= self.count { return self.substring(from: String.Index(encodedOffset: count)) } return"" } func chopSuffix(_ count: Int = 1) -> String { if count >= 0 && count <= self.count { return self.substring(to: String.Index(encodedOffset: self.count - count)) } return"" } |
斯威夫特4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | extension String { func chopPrefix(_ count: Int = 1) -> String { if count >= 0 && count <= self.count { let indexStartOfText = self.index(self.startIndex, offsetBy: count) return String(self[indexStartOfText...]) } return"" } func chopSuffix(_ count: Int = 1) -> String { if count >= 0 && count <= self.count { let indexEndOfText = self.index(self.endIndex, offsetBy: -count) return String(self[..<indexEndOfText]) } return"" } } |
在Swift 2中,执行以下操作:
1 | let cleanedString = String(theString.characters.dropFirst()) |
我建议https://www.mikeash.com/pyblog/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html来了解Swift字符串。
取决于您希望最终结果是什么(变异与非变异)。
从Swift 4.1开始:
变异:
1 2 | var str ="hello" str.removeFirst() // changes str |
非变异:
1 2 3 | let str ="hello" let strSlice = str.dropFirst() // makes a slice without the first letter let str2 = String(strSlice) |
笔记:
-
为了清楚起见,我在
nonmutating 示例中增加了一个步骤。从主观上讲,将最后两个步骤结合起来会更简洁。 -
dropFirst 的命名对我来说有点奇怪,因为如果我正确地理解了《 Swift API设计指南》,dropFirst 应该确实像dropingFirst 一样,因为它是不变的。只是一个想法 :)。
前面的答案非常好,但是到目前为止,我认为这可能是在Swift 4中从字符串中删除第一个字符的最简洁的方法:
1 2 3 4 5 6 7 | var line: String ="This is a string..." var char: Character? = nil char = line.removeFirst() print("char = \\(char)") // char = T print("line = \\(line)") // line = his is a string ... |
那这个呢?
1 | s.removeAtIndex(s.startIndex) |
当然,这假定您的字符串是可变的。它返回已删除的字符,但会更改原始字符串。
"en_US,fr_CA,es_US".chopSuffix(5).chopPrefix(5) //",fr_CA,"
1 2 3 4 5 6 7 8 9 | extension String { func chopPrefix(count: Int = 1) -> String { return self.substringFromIndex(self.startIndex.advancedBy(count)) } func chopSuffix(count: Int = 1) -> String { return self.substringToIndex(self.endIndex.advancedBy(-count)) } } |
在Swift 2中使用以下String扩展名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | extension String { func substringFromIndex(index: Int) -> String { if (index < 0 || index > self.characters.count) { print("index \\(index) out of bounds") return"" } return self.substringFromIndex(self.startIndex.advancedBy(index)) } } display.text = display.text!.substringFromIndex(1) |
我知道开箱即用就更简洁了,但是您可以轻松实现前缀
1 2 3 | public prefix func ++ <I: ForwardIndexType>(index: I) -> I { return advance(index, 1) } |
之后,您可以非常简洁地使用它:
1 | str.substringFromIndex(++str.startIndex) |
这是
1 2 3 4 5 | extension String { func chopPrefix(_ count: Int = 1) -> String { return count>self.count ? self : String(self[index(self.startIndex, offsetBy: count)...]) } } |
迅捷3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | extension String { func chopPrefix(_ count: UInt = 1) -> String { return substring(from: characters.index(startIndex, offsetBy: Int(count))) } func chopSuffix(_ count: UInt = 1) -> String { return substring(to: characters.index(endIndex, offsetBy: -Int(count))) } } class StringChopTests: XCTestCase { func testPrefix() { XCTAssertEqual("original".chopPrefix(0),"original") XCTAssertEqual("Xfile".chopPrefix(),"file") XCTAssertEqual("filename.jpg".chopPrefix(4),"name.jpg") } func testSuffix() { XCTAssertEqual("original".chopSuffix(0),"original") XCTAssertEqual("fileX".chopSuffix(),"file") XCTAssertEqual("filename.jpg".chopSuffix(4),"filename") } } |
从字符串中删除第一个字符
1 | let choppedString = String(txtField.text!.characters.dropFirst()) |