Ведущие нули для Int в Swift


305

Я хотел бы преобразовать Intв Swift вString с ведущими нулями. Например, рассмотрим этот код:

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

В настоящее время результатом этого является:

1
2
3

Но я хочу, чтобы это было:

01
02
03

Есть ли чистый способ сделать это в стандартных библиотеках Swift?

Ответы:


670

Предполагая, что вам нужно поле длиной 2 с ведущими нулями, вы должны сделать это:

import Foundation

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

вывод:

01
02
03

Это требует import Foundationтехнически, что это не часть языка Swift, а возможность, предоставляемая Foundationфреймворком. Обратите внимание, что оба import UIKitи import Cocoaвключают, Foundationпоэтому нет необходимости импортировать его снова, если вы уже импортировали Cocoaили UIKit.


Строка формата может указывать формат нескольких элементов. Например, если вы пытаетесь отформатировать 3часы, 15минуты и 7секунды, 03:15:07вы можете сделать это следующим образом:

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

вывод:

03:15:07

2
Хотя это не является частью Swift, на самом деле это выглядит очень чисто. Я думаю, что у Swift нет родного способа сделать это, так что это может быть самым близким на данный момент. Спасибо, Vacawama. :)
Jeehut

1
Кстати: если бы я просто хотел один ноль перед моим номером, я бы предпочел println("0\(myInt)")ваше предложение. Это будет использовать Swift нативный класс String вместо того, чтобы проходить форматирование NSString.
Jeehut

6
Полезно, пока вы не доберетесь до «10», хе-хе
Хосе М Пан

7
String(format: "%03d", myInt)даст тебе "000", "001", ... , "099", "100".
Vacawama

1
Это проблема, если значение, как -3, -9происходит, все равно возвращает то же самое без начального нуля.
Кодетард

139

С Swift 5 вы можете выбрать один из трех примеров, показанных ниже, чтобы решить вашу проблему.


# 1. Использование String«s init(format:_:)инициализатору

Foundationобеспечивает Swift Stringв init(format:_:)инициализатор. init(format:_:)имеет следующую декларацию:

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

Возвращает Stringобъект, инициализированный с использованием заданной строки формата в качестве шаблона, в который подставляются оставшиеся значения аргумента.

В следующем коде Playground показано, как создать Stringформат, Intсодержащий как минимум две целые цифры, используя 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. Использование String«s init(format:arguments:)инициализатору

Foundationобеспечивает Swift Stringв init(format:arguments:)инициализатор. init(format:arguments:)имеет следующую декларацию:

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

Возвращает Stringобъект, инициализированный с использованием заданной строки формата в качестве шаблона, в который подставляются оставшиеся значения аргумента в соответствии с локалью пользователя по умолчанию.

В следующем коде Playground показано, как создать Stringформат, Intсодержащий как минимум две целые цифры, используя 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. С помощьюNumberFormatter

Фонд обеспечивает NumberFormatter. Apple заявляет об этом:

Экземпляры NSNumberFormatterформатируют текстовое представление ячеек, которые содержат NSNumberобъекты и преобразуют текстовые представления числовых значений в NSNumberобъекты. Представление включает в себя целые числа, числа с плавающей запятой и двойные числа; числа с плавающей запятой и двойники могут быть отформатированы до указанной десятичной позиции.

Следующий код Playground показывает, как создать объект, NumberFormatterкоторый возвращается String?из объекта, Intсодержащего как минимум две целые цифры:

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

Я думаю, что ваш ответ правильный, если вы хотите отформатировать числа одинаково в нескольких местах. Поскольку я не просил об этом, я выбрал правильный ответ Вакавамы, но. Но спасибо за ответ! :)
Jeehut

@ImanouPetit. К вашему сведению, я использовал это с минимальным количеством цифр 3. Если я не разверну явным образом, т.е. пусть formattedNumber = formatter.stringFromNumber (counter)! тогда строки содержат Optional ("001"), поэтому мой код для динамического выбора пути к изображению не работает. Развертывание с помощью «!» Решает проблему
codecowboy

11

Для заполнения слева добавьте расширение строки, например:

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

Используя этот метод:

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

1
Зачем?! в чем преимущество этого?
Майк Глухов

7

Swift 3.0+

Левая набивка Stringрасширение похожи на padding(toLength:withPad:startingAt:)инFoundation

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

Использование:

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

1
Это может или не может работать, поскольку пользователь ожидает, если withPadпереданный аргумент больше чем один символ.
nhgrif

4

Swift 5

Ответы @imanuo уже хороши, но если вы работаете с приложением, полным чисел, вы можете рассмотреть расширение следующим образом:

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

Таким образом, вы можете позвонить куда угодно:

String(withInt: 3) 
// prints 03

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

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

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

Расширения FTW .. !! Это также хорошо работало в Swift 4. Для тех из нас, кто пытается переместить старый код с 3 на 4 и, в конце концов, на Swift 5 ... :)
Nick N

3

в Xcode 8.3.2, iOS 10.3 это хорошо сейчас

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

1

Другие ответы хороши, если вы имеете дело только с числами, использующими строку формата, но это хорошо, когда у вас могут быть строки, которые необходимо дополнить (хотя, по общему признанию, они немного отличаются от заданного вопроса, по духу похожи). Также будьте осторожны, если строка длиннее пэда.

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

Вывод "-----a str"


0

подробности

Xcode 9.0.1, swift 4.0

Решения

Данные

import Foundation

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

Решение 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"))
}

Решение 2

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

Решение 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)")
}

Как и ваш подход repeatElement, см. Мой ответ для заполнения строк.
Посен

Они не будут работать для двухзначных чисел (например, 10 становится 010). Также оригинальный вопрос задавался специально для решений с участием стандартных библиотек. Ответ выше @ImanouPetit является предпочтительным.
умный бит

-12

В отличие от других ответов, использующих средство форматирования, вы также можете просто добавить текст «0» перед каждым числом внутри цикла, например:

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

Но форматирование часто лучше, когда вы должны добавить предполагаемое количество 0 для каждого отдельного числа. Если вам нужно только добавить один 0, тогда это действительно ваш выбор.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.