Como posso usar os subscritos de corte de string no Swift 4?

294

Eu tenho o seguinte código simples escrito em Swift 3:

let str = "Hello, playground"
let index = str.index(of: ",")!
let newStr = str.substring(to: index)

No Xcode 9 beta 5, recebo o seguinte aviso:

' substring(to:)' está obsoleto: use o Stringíndice de fatiamento com um operador 'intervalo parcial de'.

Como esse índice de faturamento com intervalo parcial pode ser usado no Swift 4?

Adrian
fonte
var str = "Olá, parquinho" permite indexcut = str.firstIndex (de: ",") print (String (str [.. <indexcut!])) print (String (str [indexcut! ...]))
user1828845

Respostas:

375

Você deve deixar um lado vazio , daí o nome "intervalo parcial".

let newStr = str[..<index]

O mesmo significa intervalo parcial para os operadores, apenas deixe o outro lado vazio:

let newStr = str[index...]

Lembre-se de que esses operadores de intervalo retornam a Substring. Se você deseja convertê-lo em uma string, use Stringa função de inicialização:

let newStr = String(str[..<index])

Você pode ler mais sobre as novas substrings aqui .

Tamás Sengel
fonte
8
str[..<index]retorna a Substring. Se você quiser newStrser um Stringvocê tem que escrever:let newStr = "\(str[..<index])"
Lindemann
12
Usando interpolação de string com um solitário Substringé provavelmente um pouco confuso, uma vez que você está realmente tentando fazer é Stringinicialização: let newStr = String(str[..<index]).
Gary
5
A atualização do código em que meu valor 'index' era simplesmente um número inteiro gera uma mensagem de erro Cannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>',. Que tipos de valores devem ser usados ​​lá?
ConfusionTowers
22
@ConfusionTowers, os índices de string Swift não são números inteiros e isso não mudou na versão 4. Você provavelmente precisará de str[..<str.index(str.startIndex, offsetBy: 8)]algo assim. Lembre-se de que str.indexé uma operação de tempo linear em função de offsetBy.
precisa saber é o seguinte
6
@zneak Você provavelmente querstr.prefix(8)
Tim Vermeulen
264

Conversão Substring (Swift 3) em Fatiamento de cordas (Swift 4)

Exemplos em Swift 3, 4:

let newStr = str.substring(to: index) // Swift 3
let newStr = String(str[..<index]) // Swift 4

let newStr = str.substring(from: index) // Swift 3
let newStr = String(str[index...]) // Swift 4 

let range = firstIndex..<secondIndex // If you have a range
let newStr = = str.substring(with: range) // Swift 3
let newStr = String(str[range])  // Swift 4
Mohammad Sadegh Panadgoo
fonte
5
O Perfecto, e obrigado por dar os 3 e 4 exemplos lado a lado, facilita a atualização do meu projeto!
Ethan Parker
86

Swift 5, 4

Uso

let text = "Hello world"
text[0] // H
text[...3] // "Hell"
text[6..<text.count] // world
text[NSRange(location: 6, length: 3)] // wor

Código

import Foundation

public extension String {
  subscript(value: Int) -> Character {
    self[index(at: value)]
  }
}

public extension String {
  subscript(value: NSRange) -> Substring {
    self[value.lowerBound..<value.upperBound]
  }
}

public extension String {
  subscript(value: CountableClosedRange<Int>) -> Substring {
    self[index(at: value.lowerBound)...index(at: value.upperBound)]
  }

  subscript(value: CountableRange<Int>) -> Substring {
    self[index(at: value.lowerBound)..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeUpTo<Int>) -> Substring {
    self[..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeThrough<Int>) -> Substring {
    self[...index(at: value.upperBound)]
  }

  subscript(value: PartialRangeFrom<Int>) -> Substring {
    self[index(at: value.lowerBound)...]
  }
}

private extension String {
  func index(at offset: Int) -> String.Index {
    index(startIndex, offsetBy: offset)
  }
}
dimpiax
fonte
14
essa funcionalidade deve ser um comportamento rápido padrão.
Laimis
4
Definitivamente PR isso na lib Swift: D
OhadM 30/01/19
2
Esta é uma correção da parte mais feia do Swift.
Dmitry
@Mitry alguém não gostou, pois esta resposta tem -2. : D
dimpiax 31/05/19
Essa é uma resposta incorreta, pois o operador subscrito oculta a complexidade O (n) da função de índice. Uma boa API de programação usa apenas subscrito para indicar pesquisa rápida.
ragnarius 26/01
38

Mais curto em Swift 4/5:

var string = "123456"
string = String(string.prefix(3)) //"123"
string = String(string.suffix(3)) //"456"
ilnur
fonte
26

A conversão do seu código para o Swift 4 também pode ser feita desta maneira:

let str = "Hello, playground"
let index = str.index(of: ",")!
let substr = str.prefix(upTo: index)

Você pode usar o código abaixo para ter uma nova string:

let newString = String(str.prefix(upTo: index))
Thyerri Mezzari
fonte
17

substring (from: index) Convertido em [index ...]

Verifique a amostra

let text = "1234567890"
let index = text.index(text.startIndex, offsetBy: 3)

text.substring(from: index) // "4567890"   [Swift 3]
String(text[index...])      // "4567890"   [Swift 4]
Den
fonte
1
caracteres foram descontinuados no Swift 4, acho que você precisa alterar o exemplo para obter o índice do Swift 4
AbuTaareq
Isso me ajudou. tnx
user1105951
17

Swift5

(Método de substring do Java):

extension String {
    func subString(from: Int, to: Int) -> String {
       let startIndex = self.index(self.startIndex, offsetBy: from)
       let endIndex = self.index(self.startIndex, offsetBy: to)
       return String(self[startIndex...endIndex])
    }
}

Uso:

var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels
August Lin
fonte
2
Ainda funciona no Swift 5. Eu estava procurando por uma substring no estilo Java ( frompara to-1, por exemplo, "Hello".substring(1,4)retorna "ell"). Com uma pequena modificação ( startIndex..<endIndex), esta é a melhor solução que encontrei até agora e faz exatamente isso com apenas algumas linhas de código.
Neph 13/06/19
9

Algumas extensões úteis:

extension String {
    func substring(from: Int, to: Int) -> String {
        let start = index(startIndex, offsetBy: from)
        let end = index(start, offsetBy: to - from)
        return String(self[start ..< end])
    }

    func substring(range: NSRange) -> String {
        return substring(from: range.lowerBound, to: range.upperBound)
    }
}
Johannes
fonte
Interessante, eu estava pensando o mesmo. A seqüência de caracteres (linha ["http: //" .endIndex ...]) é mais clara que a substring obsoleta? line.substring (de: "http: //" .endIndex) talvez até que eles atinjam o objetivo declarado de manipulação incrível de strings, eles não devam descontinuar a substring.
possen
7

Exemplo de uppercasedFirstCharacterpropriedade de conveniência no Swift3 e Swift4.

A propriedade uppercasedFirstCharacterNewdemonstra como usar o índice de fatiamento de String no Swift4.

extension String {

   public var uppercasedFirstCharacterOld: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = substring(to: splitIndex).uppercased()
         let sentence = substring(from: splitIndex)
         return firstCharacter + sentence
      } else {
         return self
      }
   }

   public var uppercasedFirstCharacterNew: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = self[..<splitIndex].uppercased()
         let sentence = self[splitIndex...]
         return firstCharacter + sentence
      } else {
         return self
      }
   }
}

let lorem = "lorem".uppercasedFirstCharacterOld
print(lorem) // Prints "Lorem"

let ipsum = "ipsum".uppercasedFirstCharacterNew
print(ipsum) // Prints "Ipsum"
Vlad
fonte
1
Se você quer dizer substring (com: range) -> self [range]
Arsen Vartbaronov
6

Você pode criar seu método subString personalizado usando a extensão da classe String, como abaixo:

extension String {
    func subString(startIndex: Int, endIndex: Int) -> String {
        let end = (endIndex - self.count) + 1
        let indexStartOfText = self.index(self.startIndex, offsetBy: startIndex)
        let indexEndOfText = self.index(self.endIndex, offsetBy: end)
        let substring = self[indexStartOfText..<indexEndOfText]
        return String(substring)
    }
}
Chhaileng
fonte
Se isso vai levar um endIndex, ele precisa ser capaz de lidar também fora dos limites.
Jay
5

Criando SubString (prefixo e sufixo) a partir de String usando o Swift 4:

let str : String = "ilike"
for i in 0...str.count {
    let index = str.index(str.startIndex, offsetBy: i) // String.Index
    let prefix = str[..<index] // String.SubSequence
    let suffix = str[index...] // String.SubSequence
    print("prefix \(prefix), suffix : \(suffix)")
}

Resultado

prefix , suffix : ilike
prefix i, suffix : like
prefix il, suffix : ike
prefix ili, suffix : ke
prefix ilik, suffix : e
prefix ilike, suffix : 

Se você deseja gerar uma substring entre 2 índices, use:

let substring1 = string[startIndex...endIndex] // including endIndex
let subString2 = string[startIndex..<endIndex] // excluding endIndex
Ashis Laha
fonte
deixe prefixo = str [... <índice>] em vez de str [.. <índice>] único ponto ausente.
AbuTaareq
@AbuTaareq, de qual você está falando? deixe prefix = str [.. <index], é perfeito. (sequência de prefixo). Tente em campo de jogo para obter mais contexto.
Ashis Laha
4

Eu escrevi uma extensão de string para substituir 'String: subString:'

extension String {

    func sliceByCharacter(from: Character, to: Character) -> String? {
        let fromIndex = self.index(self.index(of: from)!, offsetBy: 1)
        let toIndex = self.index(self.index(of: to)!, offsetBy: -1)
        return String(self[fromIndex...toIndex])
    }

    func sliceByString(from:String, to:String) -> String? {
        //From - startIndex
        var range = self.range(of: from)
        let subString = String(self[range!.upperBound...])

        //To - endIndex
        range = subString.range(of: to)
        return String(subString[..<range!.lowerBound])
    }

}

Uso: "Date(1511508780012+0530)".sliceByString(from: "(", to: "+")

Resultado do exemplo : "1511508780012"

PS: Os opcionais são forçados a desembrulhar. Adicione verificação de segurança de tipo sempre que necessário.

porJeevan
fonte
Cuidado: os opcionais são forçados a desembrulhar. adicione verificação de segurança de tipo, se necessário.
byJeevan
3

Ao programar, geralmente tenho cordas com A-Za-z e 0-9. Não há necessidade de ações difíceis do Índice. Esta extensão é baseada nas funções simples esquerda / média / direita.

extension String {

    // LEFT
    // Returns the specified number of chars from the left of the string
    // let str = "Hello"
    // print(str.left(3))         // Hel
    func left(_ to: Int) -> String {
        return "\(self[..<self.index(startIndex, offsetBy: to)])"
    }

    // RIGHT
    // Returns the specified number of chars from the right of the string
    // let str = "Hello"
    // print(str.left(3))         // llo
    func right(_ from: Int) -> String {
        return "\(self[self.index(startIndex, offsetBy: self.length-from)...])"
    }

    // MID
    // Returns the specified number of chars from the startpoint of the string
    // let str = "Hello"
    // print(str.left(2,amount: 2))         // ll
    func mid(_ from: Int, amount: Int) -> String {
        let x = "\(self[self.index(startIndex, offsetBy: from)...])"
        return x.left(amount)
    }
}
Vincent
fonte
Boa ideia!! É triste, porém, que haja uma necessidade de abstrair os recursos do Swift apenas porque eles estão constantemente mudando o modo como as coisas funcionam. Acho que eles querem que todos nós nos concentremos nas construções, em vez da produtividade. De qualquer forma, eu fiz algumas pequenas atualizações para o seu código bem: pastebin.com/ManWmNnW
Fredrik Johansson
2

com esse método, você pode obter um intervalo específico de strings. você precisa passar o índice inicial e depois desse número total de caracteres que deseja.

extension String{
    func substring(fromIndex : Int,count : Int) -> String{
        let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
        let endIndex = self.index(self.startIndex, offsetBy: fromIndex + count)
        let range = startIndex..<endIndex
        return String(self[range])
    }
}
jayesh kanzariya
fonte
2

Esta é a minha solução, sem aviso, sem erros, mas perfeita

let redStr: String = String(trimmStr[String.Index.init(encodedOffset: 0)..<String.Index.init(encodedOffset: 2)])
let greenStr: String = String(trimmStr[String.Index.init(encodedOffset: 3)..<String.Index.init(encodedOffset: 4)])
let blueStr: String = String(trimmStr[String.Index.init(encodedOffset: 5)..<String.Index.init(encodedOffset: 6)])
Victor John
fonte
O uso de encodedOffseté considerado prejudicial e será preterido .
Martin R
1

Espero que isso ajude um pouco mais: -

var string = "123456789"

Se você deseja uma substring após algum índice específico.

var indexStart  =  string.index(after: string.startIndex )// you can use any index in place of startIndex
var strIndexStart   = String (string[indexStart...])//23456789

Se você deseja uma substring após remover alguma string no final.

var indexEnd  =  string.index(before: string.endIndex)
var strIndexEnd   = String (string[..<indexEnd])//12345678

você também pode criar índices com o seguinte código: -

var  indexWithOffset =  string.index(string.startIndex, offsetBy: 4)
Anurag Bhakuni
fonte
0

Espero que seja útil.

extension String {
    func getSubString(_ char: Character) -> String {
        var subString = ""
        for eachChar in self {
            if eachChar == char {
                return subString
            } else {
                subString += String(eachChar)
            }
        }
        return subString
    }
}


let str: String = "Hello, playground"
print(str.getSubString(","))
Anand Verma
fonte
0
var str = "Hello, playground"
let indexcut = str.firstIndex(of: ",")
print(String(str[..<indexcut!]))
print(String(str[indexcut!...]))

Você pode tentar dessa maneira e obterá resultados adequados.

user1828845
fonte