Qual é a maneira mais sucinta de remover o primeiro caractere de uma string no Swift?

Eu quero excluir o primeiro caractere de uma string. Até agora, a coisa mais sucinta que eu tenho é:

display.text = display.text!.substringFromIndex(advance(display.text!.startIndex, 1)) 

Eu sei que não podemos indexar em uma string com um Int por causa do Unicode, mas essa solução parece muito detalhada. Existe outra maneira que eu estou negligenciando?

Se você estiver usando o Swift 3 , poderá ignorar a segunda seção desta resposta. A boa notícia é que agora isso é novamente sucinto! Apenas usando o novo método remove (at 🙂 do String.

 var myString = "Hello, World" myString.remove(at: myString.startIndex) myString // "ello, World" 

Eu gosto da function dropFirst() global para isso.

 let original = "Hello" // Hello let sliced = dropFirst(original) // ello 

É curto, claro e funciona para qualquer coisa que esteja em conformidade com o protocolo Sliceable.

Se você estiver usando o Swift 2 , esta resposta foi alterada. Você ainda pode usar o dropFirst, mas não sem soltar o primeiro caractere da propriedade de characters strings e depois converter o resultado de volta em uma String. O dropFirst também se tornou um método, não uma function.

 let original = "Hello" // Hello let sliced = String(original.characters.dropFirst()) // ello 

Outra alternativa é usar a function de sufixo para unir o UTF16View da string. Claro, isso deve ser convertido novamente em uma String depois.

 let original = "Hello" // Hello let sliced = String(suffix(original.utf16, original.utf16.count - 1)) // ello 

Tudo isso é para dizer que a solução que eu originalmente forneci acabou não sendo a maneira mais sucinta de fazer isso em versões mais recentes do Swift. Eu recomendo retroceder na solução @chris ‘usando removeAtIndex() se você estiver procurando por uma solução curta e intuitiva.

 var original = "Hello" // Hello let removedChar = original.removeAtIndex(original.startIndex) original // ello 

E como apontado por @vacawama nos comentários abaixo, outra opção que não modifica o String original é usar substringFromIndex.

 let original = "Hello" // Hello let substring = original.substringFromIndex(advance(original.startIndex, 1)) // ello 

Ou, se acontecer de você querer eliminar um caractere do início e do final da String, você poderá usar substringWithRange. Apenas certifique-se de proteger contra a condição quando startIndex + n > endIndex - m .

 let original = "Hello" // Hello let newStartIndex = advance(original.startIndex, 1) let newEndIndex = advance(original.endIndex, -1) let substring = original.substringWithRange(newStartIndex.. 

A última linha também pode ser escrita usando a notação de subscrito.

 let substring = original[newStartIndex.. 

Atualização para o Swift 4

No Swift 4, String está de acordo com a Collection novamente, portanto, é possível usar dropFirst e dropLast para aparar os começos e fins das strings. O resultado é do tipo Substring , então você precisa passar isso para o construtor String para recuperar uma String :

 let str = "hello" let result1 = String(str.dropFirst()) // "ello" let result2 = String(str.dropLast()) // "hell" 

dropFirst() e dropLast() também usam Int para especificar o número de caracteres a serem dropLast() :

 let result3 = String(str.dropLast(3)) // "he" let result4 = String(str.dropFirst(4)) // "o" 

Se você especificar mais caracteres a serem soltos do que os da string, o resultado será a string vazia ( "" ).

 let result5 = String(str.dropFirst(10)) // "" 

Atualização para o Swift 3

Se você quiser apenas remover o primeiro caractere e quiser alterar a string original, então veja a resposta do @MickMacCallum. Se você quiser criar uma nova string no processo, use substring(from:) . Com uma extensão para String , é possível ocultar a fealdade da substring(from:) e substring(to:) para criar adições úteis para aparar o início e o fim de uma String :

 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" 

Como dropFirst e dropLast antes deles, essas funções dropLast se não houver letras suficientes disponíveis na String. O ônus está no chamador para usá-los corretamente. Esta é uma decisão de design válida. Alguém poderia escrevê-los para retornar um opcional que teria que ser desembrulhado pelo chamador.


Swift 2.x

Infelizmente no Swift 2 , dropFirst e dropLast (a melhor solução anterior) não são tão convenientes como eram antes. Com uma extensão para String , você pode ocultar a fealdade de substringFromIndex e substringToIndex :

 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" 

Como dropFirst e dropLast antes deles, essas funções dropLast se não houver letras suficientes disponíveis na String. O ônus está no chamador para usá-los corretamente. Esta é uma decisão de design válida. Alguém poderia escrevê-los para retornar um opcional que teria que ser desembrulhado pelo chamador.


No Swift 1.2 , você precisará chamar o chopPrefix assim:

 "hello".chopPrefix(count: 3) // "lo" 

ou você pode adicionar um sublinhado _ às definições de function para suprimir o nome do parâmetro:

 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)) } } 

Swift 2.2

‘advance’ não está disponível: chame o método ‘advancedBy (n)’ no índice

  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)) } 

Swift 3.0

  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)) } 

Swift 3.2

Uma visão do conteúdo da string como uma coleção de caracteres.

 @available(swift, deprecated: 3.2, message: "Please use String or Substring directly") public var characters: String.CharacterView 
 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 "" } 

Swift 4

 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[.. 

No Swift 2, faça isso:

 let cleanedString = String(theString.characters.dropFirst()) 

Eu recomendo https://www.mikeash.com/pyblog/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html para entender as strings do Swift.

O que sobre isso?

 s.removeAtIndex(s.startIndex) 

Isto, obviamente, assume que sua string é mutável. Ele retorna o caractere que foi removido, mas altera a string original.

Depende do que você quer que o resultado final seja (mutante vs não mutante).

A partir do Swift 4.1:

Mutação:

 var str = "hello" str.removeFirst() // changes str 

Não mutante:

 let str = "hello" let strSlice = str.dropFirst() // makes a slice without the first letter let str2 = String(strSlice) 

Notas:

  • Eu coloquei um passo extra no exemplo não nonmutating para maior clareza. Subjetivamente, combinar os dois últimos passos seria mais sucinto.
  • A nomeação de dropFirst parece um pouco estranha para mim, porque se eu estou entendendo o Swift API Design Guidelines corretamente, dropFirst deve ser algo como dropingFirst porque não é mutável. Apenas um pensamento :).

Eu não sei de nada mais sucinto fora da checkbox, mas você poderia facilmente implementar o prefixo ++ , por exemplo,

 public prefix func ++ (index: I) -> I { return advance(index, 1) } 

Depois que você pode usá-lo para o conteúdo do seu coração de forma muito sucinta:

 str.substringFromIndex(++str.startIndex) 

No Swift 2, use esta extensão String:

 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) 

“en_US, fr_CA, es_US” .chopSuffix (5) .chopPrefix (5) // “, fr_CA”

 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)) } } 

As respostas anteriores são muito boas, mas a partir de hoje, acho que esta pode ser a forma mais sucinta de remover o primeiro caractere de uma string no Swift 4 :

 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 ... 

Swift3

 extension String { func chopPrefix(_ count: Int = 1) -> String { return substring(from: characters.index(startIndex, offsetBy: count)) } func chopSuffix(_ count: Int = 1) -> String { return substring(to: characters.index(endIndex, offsetBy: -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") } } 

Para remover o primeiro caractere da string

 let choppedString = String(txtField.text!.characters.dropFirst()) 

Aqui está um Swift4 crash save versão da extensão chopPrefix , deixando chopSuffix para a comunidade …

 extension String { func chopPrefix(_ count: Int = 1) -> String { return count>self.count ? self : String(self[index(self.startIndex, offsetBy: count)...]) } }