Ceros a la izquierda para Int en Swift


305

Me gustaría convertir un Inten Swift a un Stringcon ceros a la izquierda. Por ejemplo, considere este código:

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

Actualmente el resultado es:

1
2
3

Pero quiero que sea:

01
02
03

¿Hay una manera limpia de hacerlo dentro de las bibliotecas estándar de Swift?

Respuestas:


670

Suponiendo que desea una longitud de campo de 2 con ceros a la izquierda, haría esto:

import Foundation

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

salida:

01
02
03

Esto requiere import Foundationque técnicamente no sea parte del lenguaje Swift sino una capacidad proporcionada por el Foundationmarco. Tenga en cuenta que ambos import UIKite import Cocoaincluir, Foundationpor lo que no es necesario volver a importarlo si ya ha importado Cocoao UIKit.


La cadena de formato puede especificar el formato de varios elementos. Por ejemplo, si está intentando formatear 3horas, 15minutos y 7segundos 03:15:07, puede hacerlo así:

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

salida:

03:15:07

2
Aunque esto no es parte de Swift, en realidad se ve muy limpio. Creo que simplemente no hay una forma nativa de Swift de hacer esto, por lo que podría ser la más cercana por ahora. Gracias vacawama. :)
Jeehut

1
Por cierto: si solo quisiera un solo cero delante de mi número, elegiría println("0\(myInt)")su sugerencia. Eso usaría la clase Swift native String en lugar de pasar por el formato NSString.
Jeehut

66
Es útil hasta llegar a "10", jeje
Jose M Pan

77
String(format: "%03d", myInt)le dará "000", "001", ... , "099", "100".
vacawama

1
Este problema si se -3, -9produce un valor similar , aún devuelve el mismo sin un cero a la izquierda.
Codetard

139

Con Swift 5, puede elegir uno de los tres ejemplos que se muestran a continuación para resolver su problema.


# 1 Usando Stringel init(format:_:)inicializador

Foundationproporciona a Swift Stringun init(format:_:)inicializador. init(format:_:)tiene la siguiente declaración:

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

Devuelve un Stringobjeto inicializado utilizando una cadena de formato dada como plantilla en la que se sustituyen los valores de argumento restantes.

El siguiente código de Playground muestra cómo crear un Stringformato Intcon al menos dos dígitos enteros utilizando 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 Usando Stringel init(format:arguments:)inicializador

Foundationproporciona a Swift Stringun init(format:arguments:)inicializador. init(format:arguments:)tiene la siguiente declaración:

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

Devuelve un Stringobjeto inicializado mediante el uso de una cadena de formato determinada como plantilla en la que los valores de argumento restantes se sustituyen según la configuración regional predeterminada del usuario.

El siguiente código de Playground muestra cómo crear un Stringformato Intcon al menos dos dígitos enteros utilizando 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 UtilizandoNumberFormatter

Fundación proporciona NumberFormatter. Apple dice al respecto:

Instancias de NSNumberFormatterformatear la representación textual de celdas que contienen NSNumberobjetos y convertir representaciones textuales de valores numéricos en NSNumberobjetos. La representación abarca enteros, flotantes y dobles; los flotantes y los dobles se pueden formatear en una posición decimal especificada.

El siguiente código de Playground muestra cómo crear un NumberFormatterque regrese String?de un Intcon al menos dos dígitos enteros:

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

Creo que su respuesta es correcta cuando desea formatear números de la misma manera en varios lugares. Como no pedí eso, elegí la respuesta de vacawama como correcta pero. Pero gracias por la respuesta! :)
Jeehut

@ImanouPetit. Para su información, utilicé esto con un número mínimo de dígitos 3. Si no desenvuelvo explícitamente, es decir, deje que formattedNumber = formatter.stringFromNumber (contador). entonces las cadenas contienen Opcional ("001") por lo que falla mi código para elegir dinámicamente una ruta de imagen. Desenvolver con '! "Resuelve el problema
codecowboy

11

Para el relleno izquierdo, agregue una extensión de cadena como esta:

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

Usando este método:

for myInt in 1...3 {
    print("\(myInt)".padLeft(totalWidth: 2, with: "0"))
}

1
¡¿por qué?! ¿Cuál es la ventaja de esto?
Mike Glukhov

7

Swift 3.0+

StringExtensión de relleno izquierdo similar a 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
    }
}

Uso:

let s = String(123)
s.leftPadding(toLength: 8, withPad: "0") // "00000123"

1
Esto puede o no funcionar como el usuario espera si el withPadargumento pasado es más de un solo carácter.
nhgrif

4

Swift 5

Las respuestas de @imanuo ya son geniales, pero si está trabajando con una aplicación llena de números, puede considerar una extensión como esta:

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 esta manera puedes llamar a donde sea:

String(withInt: 3) 
// prints 03

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

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

"54".leadingZeros(3)
// prints 054

extensiones FTW .. !! Esto también funcionó bien en Swift 4. Para aquellos de nosotros que luchan por mover el código anterior de 3 a 4, y eventualmente a Swift 5 ... :)
Nick N

3

en Xcode 8.3.2, iOS 10.3 Eso es bueno ahora

Muestra1:

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

Muestra2:

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

1

Las otras respuestas son buenas si solo se trata de números que usan la cadena de formato, pero esto es bueno cuando puede tener cadenas que necesitan ser rellenadas (aunque es cierto que es un poco diferente a la pregunta que se hace, parece similar en espíritu). Además, tenga cuidado si la cuerda es más larga que la almohadilla.

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

Salida "-----a str"


0

Detalles

Xcode 9.0.1, swift 4.0

Soluciones

Datos

import Foundation

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

Solución 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"))
}

Solución 2

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

Solución 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)")
}

Al igual que su enfoque de repetición de elemento, vea mi respuesta para las cadenas de relleno.
Posible

Estos no funcionarán para entradas de dos dígitos (por ejemplo, 10 se convierte en 010). También la pregunta original pedía específicamente soluciones que involucraran Bibliotecas Estándar. Se prefiere la respuesta anterior de @ImanouPetit.
cleverbit

-12

A diferencia de las otras respuestas que usan un formateador, también puede agregar un texto "0" delante de cada número dentro del bucle, así:

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

Pero el formateador a menudo es mejor cuando tiene que sumar, suponga una cantidad designada de 0 para cada número separado. Sin embargo, si solo necesita agregar un 0, entonces es realmente solo su elección.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.