web-dev-qa-db-fra.com

Swift 3.0 itérer sur la plage String.Index

Ce qui suit était possible avec Swift 2.2:

let m = "alpha"
for i in m.startIndex..<m.endIndex {
    print(m[i])
}
a
l
p
h
a

Avec 3.0, nous obtenons l'erreur suivante: 

Le type 'Range' (aka 'Range') n'est pas conforme au protocole 'Séquence'

J'essaie de faire une opération très simple avec des chaînes dans Swift - traverser simplement la première moitié de la chaîne (ou un problème plus générique: parcourir une plage de chaîne).

Je peux faire ce qui suit:

let s = "string"
var midIndex = s.index(s.startIndex, offsetBy: s.characters.count/2)
let r = Range(s.startIndex..<midIndex)
print(s[r])

Mais ici je ne traverse pas vraiment la corde. La question est donc de savoir comment parcourir une plage d'une chaîne donnée. Comme:

for i in Range(s.startIndex..<s.midIndex) {
    print(s[i])
}
24
p0lAris

Vous pouvez traverser une chaîne en utilisant la propriété indices de la propriété characters comme ceci: 

let letters = "string"
let middle = letters.index(letters.startIndex, offsetBy: letters.characters.count / 2)

for index in letters.characters.indices {

    // to traverse to half the length of string 
    if index == middle { break }  // s, t, r

    print(letters[index])  // s, t, r, i, n, g
}

De la section documentation in Chaînes et caractères - Compter les caractères:

Les grappes de graphèmes étendus peuvent être composées d'un ou de plusieurs scalaires Unicode. Cela signifie que différents caractères, et différentes représentations du même caractère, peuvent nécessiter différentes quantités de mémoire à stocker. De ce fait, les caractères dans Swift n'occupent pas chacun la même quantité de mémoire dans la représentation d'une chaîne. En conséquence, le nombre de caractères d'une chaîne ne peut pas être calculé sans parcourir la chaîne afin de déterminer ses limites étendues de grappes de graphèmes.

l'emphase est à moi.

Cela ne fonctionnera pas:

let secondChar = letters[1] 
// error: subscript is unavailable, cannot subscript String with an Int
25
Khundragpan

Une autre option consiste à utiliser enumerated(), par exemple:

let string = "Hello World"    
for (index, char) in string.characters.enumerated() {
    print(char)
}

ou pour Swift 4 simplement utiliser

let string = "Hello World"    
for (index, char) in string.enumerated() {
    print(char)
}
15
Andrew

Utilisez le suivant:

for i in s.characters.indices[s.startIndex..<s.endIndex]
{
  print(s[i])
}

Extrait de Migration vers Swift 2.3 ou Swift 3 depuis Swift 2.2

7
Dmitry

Itérer sur les caractères d'une chaîne est plus propre dans Swift 4:

let myString = "Hello World"    
for char in myString {
    print(char)
}
4
djruss70

Si vous voulez parcourir les caractères d'une String, au lieu d'accéder explicitement aux index de la String, vous pouvez simplement utiliser le CharacterView de la String, qui est conforme à CollectionType , vous permettant d'accéder pour mettre en ordre des méthodes de sous-séquençage telles que prefix(_:) et ainsi de suite.

/* traverse the characters of your string instance,
   up to middle character of the string, where "middle"
   will be rounded down for strings of an odd amount of
   characters (e.g. 5 characters -> travers through 2)  */
let m = "alpha"
for ch in m.characters.prefix(m.characters.count/2) {
    print(ch, ch.dynamicType)
} /* a Character
     l Character */

/* round odd division up instead */
for ch in m.characters.prefix((m.characters.count+1)/2) {
    print(ch, ch.dynamicType)
} /* a Character
     l Character 
     p Character */

Si vous souhaitez traiter les caractères de la boucle comme des chaînes, utilisez simplement String(ch) ci-dessus.


En ce qui concerne votre commentaire ci-dessous: si vous souhaitez accéder à une plage de CharacterView, vous pouvez facilement implémenter votre propre extension de CollectionType (spécifiée pour lorsque Generator.Element est Character) en utilisant à la fois prefix(_:) et suffix(_:) pour générer une sous-collection. donné par exemple une plage semi-ouverte (from..<to)

/* for values to >= count, prefixed CharacterView will be suffixed until its end */
extension CollectionType where Generator.Element == Character {
    func inHalfOpenRange(from: Int, to: Int) -> Self {
        guard case let to = min(to, underestimateCount()) where from <= to else {
            return self.prefix(0) as! Self
        }
        return self.prefix(to).suffix(to-from) as! Self
    }
}

/* example */
let m = "0123456789"    
for ch in m.characters.inHalfOpenRange(4, to: 8) {
    print(ch)         /*  \                                   */
} /* 4                     a (sub-collection) CharacterView
     5
     6
     7 */
3
dfri

La meilleure façon de faire est: - 

 let name = "nick" // The String which we want to print.

  for i in 0..<name.count 
{
   // Operation name[i] is not allowed in Swift, an alternative is
   let index = name.index[name.startIndex, offsetBy: i]
   print(name[index])
}

pour plus de détails, visitez ici

1
Nikhil Patil

Swift 4.2

Simplement:

let m = "alpha"
for i in m.indices {
   print(m[i])
}
0
Charlton Provatas

Swift 4: 

let mi: String = "hello how are you?"
for i in mi {
   print(i)
}
0
Saif

Pour démontrer concrètement comment parcourir une plage d'une chaîne dans Swift 4, nous pouvons utiliser le filtre where dans une boucle for pour filtrer son exécution dans la plage spécifiée:

func iterateStringByRange(_ sentence: String, from: Int, to: Int) {

    let startIndex = sentence.index(sentence.startIndex, offsetBy: from)
    let endIndex = sentence.index(sentence.startIndex, offsetBy: to)

    for position in sentence.indices where (position >= startIndex && position < endIndex) {
        let char = sentence[position]
        print(char)
    }

}

iterateStringByRange("string", from: 1, to: 3) imprimera t, r et i

0
teacup