Zera wiodące dla Int w Swift

305

Chciałbym przekonwertować Intw Swift na Stringwiodące zera. Na przykład rozważ ten kod:

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

Obecnie wynikiem tego jest:

1
2
3

Ale chcę, żeby to było:

01
02
03

Czy istnieje czysty sposób na zrobienie tego w standardowych bibliotekach Swift?

Jeehut
źródło

Odpowiedzi:

670

Zakładając, że chcesz mieć pole o długości 2 z wiodącymi zerami, zrobiłbyś to:

import Foundation

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

wynik:

01
02
03

Wymaga to, import Foundationwięc technicznie, nie jest to część języka Swift, ale możliwości zapewniane przez Foundationframework. Pamiętaj, że oba zawierają import UIKiti tak, więc nie trzeba importować go ponownie, jeśli już zaimportowałeś lub .import CocoaFoundationCocoaUIKit


Ciąg formatu może określać format wielu elementów. Na przykład, jeśli próbujesz sformatować 3godziny, 15minuty i 7sekundy, 03:15:07możesz to zrobić w następujący sposób:

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

wynik:

03:15:07
vacawama
źródło
2
Chociaż nie jest to częścią Swift, w rzeczywistości wygląda bardzo czysto. Myślę, że po prostu nie ma na to Swift, więc może być to na razie najbliższe. Dziękuję, vacawama. :)
Jeehut,
1
Przy okazji: gdybym chciał tylko jedno zero przed moim numerem, wybrałbym println("0\(myInt)")twoją sugestię. Użyłoby to rodzimej klasy String Swift zamiast przechodzić przez formatowanie NSString.
Jeehut
6
Przydaje się, dopóki nie dojdziesz do „10”, hehe
Jose M Pan
7
String(format: "%03d", myInt)da ci "000", "001", ... , "099", "100".
vacawama,
1
Problem -3, -9występuje, jeśli występuje wartość podobna. Nadal zwraca to samo bez wiodącego zera.
Codetard
139

W Swift 5 możesz wybrać jeden z trzech przykładów pokazanych poniżej, aby rozwiązać problem.


# 1. Korzystanie Stringz init(format:_:)inicjalizatora

Foundationzapewnia Swift Stringdo init(format:_:)inicjatora. init(format:_:)ma następującą deklarację:

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

Zwraca Stringobiekt zainicjowany przy użyciu danego ciągu formatu jako szablonu, w którym podstawione są pozostałe wartości argumentów.

Poniższy kod placu zabaw pokazuje, jak utworzyć Stringsformatowany przy Intużyciu co najmniej dwóch cyfr całkowitych przy użyciu 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. Korzystanie Stringz init(format:arguments:)inicjalizatora

Foundationzapewnia Swift Stringdo init(format:arguments:)inicjatora. init(format:arguments:)ma następującą deklarację:

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

Zwraca Stringobiekt zainicjowany przy użyciu danego ciągu formatu jako szablonu, w którym pozostałe wartości argumentów są podstawiane zgodnie z domyślnymi ustawieniami narodowymi użytkownika.

Poniższy kod placu zabaw pokazuje, jak utworzyć Stringsformatowany przy Intużyciu co najmniej dwóch cyfr całkowitych przy użyciu 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. Za pomocąNumberFormatter

Fundacja zapewnia NumberFormatter. Apple mówi o tym:

Instancje NSNumberFormatterformatowania reprezentacji tekstowej komórek zawierających NSNumberobiekty i konwertowania reprezentacji tekstowych wartości liczbowych na NSNumberobiekty. Reprezentacja obejmuje liczby całkowite, liczby zmiennoprzecinkowe i liczby podwójne; liczba zmiennoprzecinkowa i liczba podwójna mogą być sformatowane do określonej pozycji dziesiętnej.

Poniższy kod przedstawia zabaw dla dzieci, jak stworzyć NumberFormatterzwracającej String?od a Into co najmniej dwóch cyfr całkowitych:

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
źródło
Myślę, że Twoja odpowiedź jest słuszna, gdy chcesz sformatować liczby w ten sam sposób w wielu miejscach. Ponieważ nie prosiłem o to, wybrałem odpowiedź vacawama jako poprawną, ale. Ale dziękuję za odpowiedź! :)
Jeehut,
@ImanouPetit. Do twojej wiadomości, użyłem tego z minimalną liczbą cyfr 3. Jeśli nie jawnie rozpakuj, tj. Pozwól formattedNumber = formatter.stringFromNumber (licznik)! następnie ciągi zawierają Opcjonalne („001”), więc mój kod do dynamicznego wybierania ścieżki obrazu kończy się niepowodzeniem. Rozpakowanie za pomocą „!” Rozwiązuje problem
codecowboy
11

Dla lewego dopełnienia dodaj przedłużenie łańcucha takie jak to:

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

Za pomocą tej metody:

for myInt in 1...3 {
    print("\(myInt)".padLeft(totalWidth: 2, with: "0"))
}
Kiran P. Nair
źródło
1
dlaczego?! jaka jest z tego zaleta?
Mike Glukhov
7

Swift 3.0+

Lewe Stringprzedłużenie wyściółki podobne do padding(toLength:withPad:startingAt:)wFoundation

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

Stosowanie:

let s = String(123)
s.leftPadding(toLength: 8, withPad: "0") // "00000123"
John Cromie
źródło
1
Może to działać lub nie, zgodnie z oczekiwaniami użytkownika, jeśli withPadprzekazany argument jest więcej niż pojedynczy znak.
nhgrif
4

Szybki 5

Odpowiedzi @imanuo są już świetne, ale jeśli pracujesz z aplikacją pełną, możesz rozważyć takie rozszerzenie:

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

}

W ten sposób możesz dzwonić wszędzie:

String(withInt: 3) 
// prints 03

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

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

"54".leadingZeros(3)
// prints 054
Luca Davanzo
źródło
rozszerzenia FTW .. !! Działa to również dobrze w Swift 4. Dla tych z nas, którzy starają się przenieść starszy kod z 3, na 4, a ostatecznie do Swift 5 ... :)
Nick N
3

w Xcode 8.3.2, iOS 10.3 To jest na razie dobre

Próbka 1:

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

Próbka 2:

let dayMoveRaw = 55 
let dayMove = String(format: "%02d", arguments: [dayMoveRaw])
print(dayMove) // 55
Steffen
źródło
1

Inne odpowiedzi są dobre, jeśli masz do czynienia tylko z liczbami za pomocą ciągu formatującego, ale jest to dobre, gdy możesz mieć ciągi, które wymagają uzupełnienia (choć wprawdzie nieco inne niż zadane pytanie, wydaje się podobne w duchu). Uważaj również, jeśli sznurek jest dłuższy niż podkładka.

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

Wynik "-----a str"

possen
źródło
0

Detale

Xcode 9.0.1, szybki 4.0

Rozwiązania

Dane

import Foundation

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

Rozwiązanie 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"))
}

Rozwiązanie 2

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

Rozwiązanie 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)")
}
Wasilij Bodnarchuk
źródło
Podobnie jak w przypadku metody repeatElement, zobacz moją odpowiedź dotyczącą ciągów dopełniających.
possen
Nie będą działać dla dwucyfrowych liczb całkowitych (np. 10 staje się 010). Również oryginalne pytanie zadane specjalnie dla rozwiązań obejmujących biblioteki standardowe. Preferowana jest powyższa odpowiedź autorstwa @ImanouPetit.
cleverbit
-12

W przeciwieństwie do innych odpowiedzi, które używają formatera, możesz również po prostu dodać tekst „0” przed każdą liczbą wewnątrz pętli, w następujący sposób:

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

Ale formatyzator jest często lepszy, gdy trzeba dodać, przypuszczalnie określoną liczbę zerową dla każdej oddzielnej liczby. Jeśli jednak musisz dodać tylko jedno 0, to naprawdę jest to twój wybór.

Eric Zhou
źródło