Swift中整数的前导零

402

我想将Swift中的Int转换为带有前导零的String。例如,考虑以下代码:

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

目前的结果是:

1
2
3

但是我希望它是这样的:

01
02
03

在Swift标准库中,有没有一种简洁的方法来做到这一点?


请使用String(format: !!! - Fattie
1
只需使用 String(format: "%04d", 42),就是这么简单。 - Fattie
12个回答

874
假设您想要一个长度为2的字段,并且希望在前面填充零,您可以这样做:
import Foundation

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

输出:

01
02
03
这需要import Foundation,所以从技术上讲它不是Swift语言的一部分,而是由Foundation框架提供的功能。请注意,import UIKitimport Cocoa都包含Foundation,所以如果您已经导入了CocoaUIKit,则不需要再次导入它。
格式字符串可以指定多个项目的格式。例如,如果您想将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
9
直到你达到“10”,它就很有用了,呵呵。 - Jose M Pan
9
String(format: "%03d", myInt) 会给你 "000", "001", ... , "099", "100" - vacawama
1
如果出现像“-3,-9”这样的值,则存在问题,它仍然返回相同的结果而没有前导零。 - Codetard
显示剩余4条评论

189

在 Swift 5 中,您可以从下面展示的三个示例中选择一个来解决问题。


#1. 使用 Stringinit(format:_:) 初始化程序

Foundation 为 Swift String 提供了 init(format:_:) 初始化程序。 init(format:_:) 具有以下声明:

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

通过将剩余的参数值替换到给定格式字符串中,返回一个String对象。

以下Playground代码展示了如何使用init(format:_:)创建至少具有两个整数位的Int格式化的String

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. 使用 Stringinit(format:arguments:) 初始化器

Foundation 为 Swift 的 String 提供了一个 init(format:arguments:) 初始化器。 init(format:arguments:) 具有以下声明:

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

通过使用给定的格式字符串作为模板,初始化一个String对象,根据用户的默认语言环境将其余参数值替换到模板中。

以下Playground代码展示了如何使用init(format:arguments:)创建一个至少包含两个整数位的Int格式化后的String

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是Foundation提供的。苹果公司对它的说明如下:

NSNumberFormatter类实例可以将包含NSNumber对象的单元格的文本表示形式格式化,并将数字值的文本表示形式转换为NSNumber对象。该表示包括整数、浮点数和双精度浮点数;浮点数和双精度浮点数可以被格式化为指定的小数位数。

以下Playground代码演示了如何创建一个NumberFormatter,它从至少有两个整数位的Int转换成String?

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

我认为你的回答是正确的,当你想在多个地方以相同的方式格式化数字时。由于我没有要求这样做,所以我选择了vacawama的答案作为正确答案。但是还是谢谢你的回答! :) - Jeehut
@ImanouPetit。顺便说一下,我使用了最少的3个数字。如果我不显式解包,即让formattedNumber = formatter.stringFromNumber(counter)!,那么字符串将包含Optional("001"),因此我的代码动态选择图像路径失败。使用'!'解包可以解决这个问题。 - codecowboy

19

要进行左侧填充,请添加以下字符串扩展:

extension String {

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

使用这种方法:

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

1
为什么?!这有什么优势吗? - Mike Glukhov
这个答案是非常错误的。只需要使用 String(format: "%04d", 42) 即可,它当然完全内置于 Swift 中。 - Fattie

10

Swift 3.0+

这是一个左填充字符串的扩展,类似于Foundation中的padding(toLength:withPad:startingAt:)方法。

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

7

使用 Swift 5 引入的可扩展插值功能:

extension DefaultStringInterpolation {
    mutating func appendInterpolation(pad value: Int, toWidth width: Int, using paddingCharacter: Character = "0") {
        appendInterpolation(String(format: "%\(paddingCharacter)\(width)d", value))
    }
}

let pieCount = 3
print("I ate \(pad: pieCount, toWidth: 3, using: "0") pies")  // => `I ate 003 pies`
print("I ate \(pad: 1205, toWidth: 3, using: "0") pies")  // => `I ate 1205 pies`

7

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

扩展万岁!!这也可以在Swift 4中很好地工作。对于我们这些努力将旧代码从3移动到4,最终到Swift 5的人来说... :) - Nick N
1
命名完全错误。 "前导零" 不会给你 "前导零"。它只会给你一个相应长度的字符串。 - Fattie
“fillWithInitialZerosTheStringLenght(2)” 这个写法好像不太合适,你有其他建议吗? - Luca Davanzo

4
其他答案提供的方法适用于只处理数字的格式字符串,但是如果你需要填充字符串(尽管与问题有些不同,但类似),这种方法就很好了。另外,如果字符串比填充内容短,请小心处理。
   let str = "a str"
   let padAmount = max(10, str.count)
   String(repeatElement("-", count: padAmount - str.count)) + str

输出 "-----一个字符串"


3

在Xcode 8.3.2和iOS 10.3中,这是一个好消息。

示例1:

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

3
下面的代码生成一个带有0填充的3位数字字符串:
import Foundation

var randomInt = Int.random(in: 0..<1000)
var str = String(randomInt)
var paddingZero = String(repeating: "0", count: 3 - str.count)

print(str, str.count, paddingZero + str)

输出:

5 1 005
88 2 088
647 3 647

0
在Swift 4及以上版本中,您也可以尝试这样做:

func leftPadding(valueString: String, toLength: Int, withPad: String = " ") -> String {
        guard toLength > valueString.count else { return valueString }
        
        let padding = String(repeating: withPad, count: toLength - valueString.count)
        return padding + valueString
    }

call the function:

leftPadding(valueString: "12", toLength: 5, withPad: "0")

输出: "00012"


1
只需使用String(format: "%04d", 42)。当然,它完全内置于Swift中。 - Fattie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接