【问题标题】:Leading zeros for Int in SwiftSwift 中 Int 的前导零
【发布时间】:2014-10-23 08:46:11
【问题描述】:

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

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

目前它的结果是:

1
2
3

但我希望它是:

01
02
03

在 Swift 标准库中是否有一种干净的方式来执行此操作?

【问题讨论】:

    标签: string swift int type-conversion


    【解决方案1】:

    为左填充添加这样的字符串扩展:

    Swift 5.0 +

    extension String {
        func PadLeft( totalWidth: Int,byString:String) -> String {
        let toPad = totalWidth - self.count
        if toPad < 1 {
            return self
        }
        
        return "".padding(toLength: toPad, withPad: byString, startingAt: 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"))
    }
    

    【讨论】:

    • 为什么?!这样做有什么好处?
    【解决方案2】:

    使用 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`
    

    【讨论】:

      【解决方案3】:

      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
          }
      

      调用函数:

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

      输出: “00012”

      【讨论】:

        【解决方案4】:

        斯威夫特 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 的人来说... :)
        【解决方案5】:

        使用 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:) 创建一个格式为 IntString,其中至少包含两个整数数字:

        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。苹果对此表示:

        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 的答案作为正确的答案。不过谢谢你的回答! :)
        • @ImanouPetit。仅供参考,我将其与最小数字 3 一起使用。如果我没有明确打开包装,即让 formattedNumber = formatter.stringFromNumber(counter)!然后字符串包含 Optional("001") 所以我动态选择图像路径的代码失败。用 '!" 解包解决了问题
        【解决方案6】:

        假设您想要一个长度为 2 且带有前导零的字段,您可以这样做:

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

        输出:

        01
        02
        03
        

        这需要import Foundation,所以从技术上讲,它不是 Swift 语言的一部分,而是Foundation 框架提供的功能。注意import UIKitimport 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
        

        【讨论】:

        • 虽然这不是 Swift 的一部分,但它实际上看起来很干净。我认为没有一种 Swift 原生的方式可以做到这一点,所以这可能是目前最接近的。谢谢你,瓦卡瓦玛。 :)
        • 顺便说一句:如果我只想在我的号码前加一个零,我会选择println("0\(myInt)") 而不是您的建议。那将使用 Swift 本机 String 类而不是通过 NSString 格式化。
        • 在你达到“10”之前很有用,呵呵
        • String(format: "%03d", myInt) 会给你"000", "001", ... , "099", "100"
        • 如果出现像-3, -9 这样的值,它仍然会返回相同的值而没有前导零。
        【解决方案7】:

        详情

        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 上面的答案是首选。
        【解决方案8】:

        如果您仅使用格式字符串处理数字,则其他答案很好,但是当您可能需要填充字符串时,这很好(尽管与所提出的问题有些不同,但在精神上似乎相似) .另外,如果字符串比焊盘长,请小心。

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

        输出"-----a str"

        【讨论】:

          【解决方案9】:

          在 Xcode 8.3.2、iOS 10.3 中 到现在就好了

          样本 1:

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

          样本 2:

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

          【讨论】:

            【解决方案10】:

            Swift 3.0+

            左填充 String 扩展类似于 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"
            

            【讨论】:

            • 如果传递的withPad 参数不止一个字符,这可能会也可能不会像用户期望的那样工作。
            【解决方案11】:

            与使用格式化程序的其他答案不同,您也可以在循环内的每个数字前面添加一个“0”文本,如下所示:

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

            但是,当您必须为每个单独的数字添加指定数量的 0 时,格式化程序通常会更好。但是,如果您只需要添加一个 0,那么它真的只是您的选择。

            【讨论】:

              猜你喜欢
              • 2019-04-14
              • 1970-01-01
              • 1970-01-01
              • 2019-10-05
              • 2023-01-18
              • 2011-10-09
              相关资源
              最近更新 更多