Quero converter o índice de uma letra contida em uma string em um valor inteiro. Tentei ler os arquivos de cabeçalho, mas não consigo encontrar o tipo Index
, embora pareça estar em conformidade com o protocolo ForwardIndexType
com métodos (por exemplo distanceTo
).
var letters = "abcdefg"
let index = letters.characters.indexOf("c")!
// ERROR: Cannot invoke initializer for type 'Int' with an argument list of type '(String.CharacterView.Index)'
let intValue = Int(index) // I want the integer value of the index (e.g. 2)
Qualquer ajuda é apreciada.
let index = letters.characters.index(of: "c")
próxima linhalet int_index = letters.characters.distance(from: letters.startIndex, to: index)
Respostas:
editar / atualizar:
Xcode 11 • Swift 5.1 ou posterior
extension StringProtocol { func distance(of element: Element) -> Int? { firstIndex(of: element)?.distance(in: self) } func distance<S: StringProtocol>(of string: S) -> Int? { range(of: string)?.lowerBound.distance(in: self) } }
extension Collection { func distance(to index: Index) -> Int { distance(from: startIndex, to: index) } }
extension String.Index { func distance<S: StringProtocol>(in string: S) -> Int { string.distance(to: self) } }
Teste de playground
let letters = "abcdefg" let char: Character = "c" if let distance = letters.distance(of: char) { print("character \(char) was found at position #\(distance)") // "character c was found at position #2\n" } else { print("character \(char) was not found") }
let string = "cde" if let distance = letters.distance(of: string) { print("string \(string) was found at position #\(distance)") // "string cde was found at position #2\n" } else { print("string \(string) was not found") }
fonte
Swift 4
var str = "abcdefg" let index = str.index(of: "c")?.encodedOffset // Result: 2
Nota: Se String contiver os mesmos caracteres múltiplos, ele obterá apenas o mais próximo da esquerda
var str = "abcdefgc" let index = str.index(of: "c")?.encodedOffset // Result: 2
fonte
"🇺🇸🇺🇸🇧🇷".index(of: "🇧🇷")?.encodedOffset // 16
encodedOffset
foi descontinuado do Swift 4.2 .Mensagem de descontinuação:
encodedOffset
foi descontinuada porque o uso mais comum é incorreto. Useutf16Offset(in:)
para obter o mesmo comportamento.Então, podemos usar
utf16Offset(in:)
assim:var str = "abcdefgc" let index = str.index(of: "c")?.utf16Offset(in: str) // Result: 2
fonte
let str = "🇺🇸🇺🇸🇧🇷"
let index = str.firstIndex(of: "🇧🇷")?.utf16Offset(in: str)
// Resultado: 8Ao pesquisar um índice como este
⛔️ guard let index = (positions.firstIndex { position <= $0 }) else {
ele é tratado como Array.Index. Você tem que dar ao compilador uma pista de que você quer um inteiro
✅ guard let index: Int = (positions.firstIndex { position <= $0 }) else {
fonte
Para executar a operação de string com base no índice, você não pode fazer isso com a abordagem numérica de índice tradicional. porque swift.index é recuperado pela função indices e não é do tipo Int. Mesmo que String seja uma matriz de caracteres, ainda não podemos ler elemento por índice.
Isso é frustrante.
Portanto, para criar uma nova substring de cada caractere par da string, verifique o código abaixo.
let mystr = "abcdefghijklmnopqrstuvwxyz" let mystrArray = Array(mystr) let strLength = mystrArray.count var resultStrArray : [Character] = [] var i = 0 while i < strLength { if i % 2 == 0 { resultStrArray.append(mystrArray[i]) } i += 1 } let resultString = String(resultStrArray) print(resultString)
Resultado: acegikmoqsuwy
Desde já, obrigado
fonte
var counter = 0
let result = mystr.filter { _ in
defer { counter += 1 }
return counter.isMultiple(of: 2)
}
var index = mystr.startIndex
let result = mystr.filter { _ in
defer { mystr.formIndex(after: &index) }
return mystr.distance(from: mystr.startIndex, to: index).isMultiple(of: 2)
}
Esta é uma extensão que permitirá que você acesse os limites de uma substring como
Int
s em vez deString.Index
valores:import Foundation /// This extension is available at /// https://gist.github.com/zackdotcomputer/9d83f4d48af7127cd0bea427b4d6d61b extension StringProtocol { /// Access the range of the search string as integer indices /// in the rendered string. /// - NOTE: This is "unsafe" because it may not return what you expect if /// your string contains single symbols formed from multiple scalars. /// - Returns: A `CountableRange<Int>` that will align with the Swift String.Index /// from the result of the standard function range(of:). func countableRange<SearchType: StringProtocol>( of search: SearchType, options: String.CompareOptions = [], range: Range<String.Index>? = nil, locale: Locale? = nil ) -> CountableRange<Int>? { guard let trueRange = self.range(of: search, options: options, range: range, locale: locale) else { return nil } let intStart = self.distance(from: startIndex, to: trueRange.lowerBound) let intEnd = self.distance(from: trueRange.lowerBound, to: trueRange.upperBound) + intStart return Range(uncheckedBounds: (lower: intStart, upper: intEnd)) } }
Esteja ciente de que isso pode causar estranheza, e é por isso que a Apple optou por tornar isso difícil. (Embora seja uma decisão de design discutível - esconder uma coisa perigosa apenas tornando-a difícil ...)
Você pode ler mais na documentação do String da Apple , mas o tldr é que decorre do fato de que esses "índices" são, na verdade, específicos de implementação. Eles representam os índices na string após ela ter sido processada pelo sistema operacional e, portanto, podem mudar de sistema operacional para sistema operacional, dependendo de qual versão da especificação Unicode está sendo usada. Isso significa que acessar valores por índice não é mais uma operação de tempo constante, porque a especificação UTF deve ser executada sobre os dados para determinar o local correto na string. Esses índices também não se alinham com os valores gerados por NSString, se você fizer uma ponte para ele, ou com os índices nos escalares UTF subjacentes. Aviso ao desenvolvedor.
fonte
func rangeInt<S: StringProtocol>(of aString: S, options: String.CompareOptions = []) -> Range<Int>? {
guard let range = range(of: aString, options: options) else { return nil }
let start = distance(from: startIndex, to: range.lowerBound)
return start..<start+distance(from: range.lowerBound, to: range.upperBound)
}
countableRange
e retornariaCountableRange