Zéros de tête pour Int dans Swift

305

Je voudrais convertir un IntSwift en un Stringavec des zéros non significatifs. Par exemple, considérez ce code:

for myInt in 1 ... 3 {
    print("\(myInt)")
}

Actuellement, le résultat est:

1
2
3

Mais je veux que ce soit:

01
02
03

Existe-t-il un moyen propre de le faire dans les bibliothèques standard Swift?

Jeehut
la source

Réponses:

670

En supposant que vous vouliez une longueur de champ de 2 avec des zéros en tête, vous feriez ceci:

import Foundation

for myInt in 1 ... 3 {
    print(String(format: "%02d", myInt))
}

production:

01
02
03

Cela nécessite import Foundationdonc techniquement que ce n'est pas une partie du langage Swift mais une capacité fournie par le Foundationframework. Notez que les deux import UIKitet import Cocoaincluent Foundationdonc il n'est pas nécessaire de l'importer à nouveau si vous avez déjà importé Cocoaou UIKit.


La chaîne de format peut spécifier le format de plusieurs éléments. Par exemple, si vous essayez de formater des 3heures, des 15minutes et des 7secondes, 03:15:07vous pouvez le faire comme ceci:

let hours = 3
let minutes = 15
let seconds = 7
print(String(format: "%02d:%02d:%02d", hours, minutes, seconds))

production:

03:15:07
vacawama
la source
2
Bien que cela ne fasse pas partie de Swift, il semble en fait très propre. Je pense qu'il n'y a tout simplement pas de méthode native pour Swift, donc cela pourrait être le plus proche pour l'instant. Merci, vacawama. :)
Jeehut
1
Soit dit en passant: si je voulais juste un zéro unique devant mon numéro, je choisirais println("0\(myInt)")plutôt votre suggestion. Cela utiliserait la classe String native Swift au lieu de passer par le formatage NSString.
Jeehut
6
Est utile jusqu'à ce que vous arriviez à "10", hehe
Jose M Pan
7
String(format: "%03d", myInt)vous donnera "000", "001", ... , "099", "100".
vacawama
1
Ce problème se produit si une valeur similaire -3, -9se produit, il retourne toujours le même sans zéro de tête.
Codetard
139

Avec Swift 5, vous pouvez choisir l'un des trois exemples ci-dessous pour résoudre votre problème.


#1. Utilisation de Stringl' init(format:_:)initialiseur de

Foundationfournit à Swift Stringun init(format:_:)initialiseur. init(format:_:)a la déclaration suivante:

init(format: String, _ arguments: CVarArg...)

Renvoie un Stringobjet initialisé en utilisant une chaîne de format donnée comme modèle dans lequel les valeurs d'argument restantes sont substituées.

Le code Playground suivant montre comment créer un Stringformaté à partir Intd'au moins deux chiffres entiers à l'aide de init(format:_:):

import Foundation

let string0 = String(format: "%02d", 0) // returns "00"
let string1 = String(format: "%02d", 1) // returns "01"
let string2 = String(format: "%02d", 10) // returns "10"
let string3 = String(format: "%02d", 100) // returns "100"

# 2. Utilisation de Stringl' init(format:arguments:)initialiseur de

Foundationfournit à Swift Stringun init(format:arguments:)initialiseur. init(format:arguments:)a la déclaration suivante:

init(format: String, arguments: [CVarArg])

Renvoie un Stringobjet initialisé en utilisant une chaîne de format donnée comme modèle dans lequel les valeurs d'argument restantes sont substituées en fonction des paramètres régionaux par défaut de l'utilisateur.

Le code Playground suivant montre comment créer un Stringformaté à partir Intd'au moins deux chiffres entiers à l'aide de init(format:arguments:):

import Foundation

let string0 = String(format: "%02d", arguments: [0]) // returns "00"
let string1 = String(format: "%02d", arguments: [1]) // returns "01"
let string2 = String(format: "%02d", arguments: [10]) // returns "10"
let string3 = String(format: "%02d", arguments: [100]) // returns "100"

# 3. En utilisantNumberFormatter

Fondation fournit NumberFormatter. Apple déclare à ce sujet:

Les instances de NSNumberFormatterformatage de la représentation textuelle des cellules qui contiennent des NSNumberobjets et convertissent les représentations textuelles des valeurs numériques en NSNumberobjets. La représentation comprend des entiers, des flottants et des doubles; les flottants et les doubles peuvent être formatés à une position décimale spécifiée.

Le code Playground suivant montre comment créer un NumberFormatterqui renvoie String?un Intavec au moins deux chiffres entiers:

import Foundation

let formatter = NumberFormatter()
formatter.minimumIntegerDigits = 2

let optionalString0 = formatter.string(from: 0) // returns Optional("00")
let optionalString1 = formatter.string(from: 1) // returns Optional("01")
let optionalString2 = formatter.string(from: 10) // returns Optional("10")
let optionalString3 = formatter.string(from: 100) // returns Optional("100")
Imanou Petit
la source
Je pense que votre réponse est juste lorsque vous souhaitez formater des nombres de la même manière à plusieurs endroits. Comme je n'ai pas demandé cela, j'ai choisi la réponse de vacawama comme correcte mais. Mais merci pour la réponse! :)
Jeehut
@ImanouPetit. Pour info, j'ai utilisé ceci avec un nombre minimum de chiffres 3. Si je ne déballe pas explicitement, c'est-à-dire que formatedNumber = formatter.stringFromNumber (counter)! alors les chaînes contiennent Facultatif ("001") donc mon code pour choisir dynamiquement un chemin d'image échoue. Déballer avec '! "
Résout
11

Pour le remplissage gauche, ajoutez une extension de chaîne comme celle-ci:

Swift 2.0 +

extension String {
    func padLeft (totalWidth: Int, with: String) -> String {
        let toPad = totalWidth - self.characters.count
        if toPad < 1 { return self }
        return "".stringByPaddingToLength(toPad, withString: with, startingAtIndex: 0) + self
    }
}

Swift 3.0 +

extension String {
    func padLeft (totalWidth: Int, with: String) -> String {
        let toPad = totalWidth - self.characters.count
        if toPad < 1 { return self }
        return "".padding(toLength: toPad, withPad: with, startingAt: 0) + self
    }
}

En utilisant cette méthode:

for myInt in 1...3 {
    print("\(myInt)".padLeft(totalWidth: 2, with: "0"))
}
Kiran P Nair
la source
1
Pourquoi?! quel est l'avantage de cela?
Mike Glukhov
7

Swift 3.0+

Padding gauche Stringextension similaire à padding(toLength:withPad:startingAt:)enFoundation

extension String {
    func leftPadding(toLength: Int, withPad: String = " ") -> String {

        guard toLength > self.characters.count else { return self }

        let padding = String(repeating: withPad, count: toLength - self.characters.count)
        return padding + self
    }
}

Usage:

let s = String(123)
s.leftPadding(toLength: 8, withPad: "0") // "00000123"
John Cromie
la source
1
Cela peut ou peut ne pas fonctionner comme prévu par l'utilisateur si l' withPadargument transmis est supérieur à un seul caractère.
nhgrif
4

Swift 5

@imanuo réponses est déjà génial, mais si vous travaillez avec une application pleine de nombre, vous pouvez envisager une extension comme celle-ci:

extension String {

    init(withInt int: Int, leadingZeros: Int = 2) {
        self.init(format: "%0\(leadingZeros)d", int)
    }

    func leadingZeros(_ zeros: Int) -> String {
        if let int = Int(self) {
            return String(withInt: int, leadingZeros: zeros)
        }
        print("Warning: \(self) is not an Int")
        return ""
    }
    
}

De cette façon, vous pouvez appeler partout:

String(withInt: 3) 
// prints 03

String(withInt: 23, leadingZeros: 4) 
// prints 0023

"42".leadingZeros(2)
// prints 42

"54".leadingZeros(3)
// prints 054
Luca Davanzo
la source
extensions FTW .. !! Cela a également bien fonctionné dans Swift 4. Pour ceux d'entre nous qui ont du mal à déplacer l'ancien code de 3, à 4, et finalement à Swift 5 ... :)
Nick N
3

dans Xcode 8.3.2, iOS 10.3 C'est bien maintenant

Sample1:

let dayMoveRaw = 5 
let dayMove = String(format: "%02d", arguments: [dayMoveRaw])
print(dayMove) // 05

Sample2:

let dayMoveRaw = 55 
let dayMove = String(format: "%02d", arguments: [dayMoveRaw])
print(dayMove) // 55
Steffen
la source
1

Les autres réponses sont bonnes si vous ne traitez qu'avec des nombres utilisant la chaîne de format, mais cela est bon lorsque vous pouvez avoir des chaînes qui doivent être remplies (bien qu'il soit vrai qu'un peu différent de la question posée, semble similaire dans l'esprit). Faites également attention si la chaîne est plus longue que le pad.

   let str = "a str"
   let padAmount = max(10, str.count)
   String(repeatElement("-", count: padAmount - str.count)) + str

Production "-----a str"

possen
la source
0

Détails

Xcode 9.0.1, swift 4.0

Solutions

Les données

import Foundation

let array = [0,1,2,3,4,5,6,7,8]

Solution 1

extension Int {

    func getString(prefix: Int) -> String {
        return "\(prefix)\(self)"
    }

    func getString(prefix: String) -> String {
        return "\(prefix)\(self)"
    }
}

for item in array {
    print(item.getString(prefix: 0))
}

for item in array {
    print(item.getString(prefix: "0x"))
}

Solution 2

for item in array {
    print(String(repeatElement("0", count: 2)) + "\(item)")
}

Solution 3

extension String {

    func repeate(count: Int, string: String? = nil) -> String {

        if count > 1 {
            let repeatedString = string ?? self
            return repeatedString + repeate(count: count-1, string: repeatedString)
        }
        return self
    }
}

for item in array {
    print("0".repeate(count: 3) + "\(item)")
}
Vasily Bodnarchuk
la source
Comme votre approche repeatElement, consultez ma réponse pour les chaînes de remplissage.
possédé
Ceux-ci ne fonctionneront pas pour les entiers à deux chiffres (par exemple, 10 devient 010). De plus, la question d'origine demandait spécifiquement des solutions impliquant des bibliothèques standard. La réponse ci-dessus par @ImanouPetit est préférée.
cleverbit
-12

Contrairement aux autres réponses qui utilisent un formateur, vous pouvez également simplement ajouter un texte "0" devant chaque numéro à l'intérieur de la boucle, comme ceci:

for myInt in 1...3 {
    println("0" + "\(myInt)")
}

Mais le formateur est souvent meilleur lorsque vous devez ajouter supposons une quantité désignée de 0 pour chaque nombre séparé. Si vous n'avez besoin que d'ajouter un 0, c'est vraiment votre choix.

Eric Zhou
la source