【问题标题】:Padding a swift String for printing填充快速字符串以进行打印
【发布时间】:2015-11-27 01:48:27
【问题描述】:

我正在尝试打印所有填充到相同宽度的字符串列表。

在 C 语言中,我会使用 printf("%40s", cstr), 之类的东西,其中 cstr 是 C 字符串。

在 Swift 中,我能想到的最好的方法是:

line += String(format: "%40s",string.cStringUsingEncoding(<someEncoding>))

有没有更好的办法?

【问题讨论】:

    标签: swift string padding


    【解决方案1】:

    Swift 3 中,您可以使用:

    let str = "Test string"
    let paddedStr = str.padding(toLength: 20, withPad: " ", startingAt: 0)
    

    结果字符串:"Test string "

    如果您需要向左填充文本(右对齐),您可以编写以下函数作为String的扩展:

    extension String {
        func leftPadding(toLength: Int, withPad character: Character) -> String {
            let newLength = self.characters.count
            if newLength < toLength {
                return String(repeatElement(character, count: toLength - newLength)) + self
            } else {
                return self.substring(from: index(self.startIndex, offsetBy: newLength - toLength))
            }
        }
    }
    

    所以如果你写:

    let str = "Test string"
    let paddedStr = str.leftPadding(toLength: 20, withPad: " ")
    

    结果字符串:" Test string"

    Swift 4.1 中,substring 方法已被弃用,并且有许多新方法可以获取子字符串。 prefixsuffix 或使用Range&lt;String.Index&gt;String 下标。

    对于之前的扩展,我们可以使用suffix 方法来实现相同的结果。由于suffix方法返回的是String.SubSequence,所以在返回之前需要转换成String

    extension String {
        func leftPadding(toLength: Int, withPad character: Character) -> String {
            let stringLength = self.count
            if stringLength < toLength {
                return String(repeatElement(character, count: toLength - stringLength)) + self
            } else {
                return String(self.suffix(toLength))
            }
        }
    }
    

    【讨论】:

    • 完美!谢谢!
    • String 上的字符也已被弃用
    • 编辑了 Swift 4 版本以反映 characters 属性的弃用。
    • Foundation 方法 padding:toLength: 允许填充字符不止一个字符。这个答案失去了这种能力。
    【解决方案2】:

    对于 Swift >= 3

    line += string.padding(toLength: 40, withPad: " ", startingAt: 0)
    

    对于斯威夫特

    NSStringstringByPaddingToLength: 方法:

    line += string.stringByPaddingToLength(40, withString: " ", startingAtIndex: 0)
    

    【讨论】:

    • 要向左侧添加填充,我们必须编写自己的代码。扩展 String { func PadLeft(totalWidth: Int,byString:String) -> String { let toPad = totalWidth - self.characters 。数数;如果 toPad
    • 如果字符串长度超过您的长度(在这种情况下为 40 个字符),此方法还将截断您的字符串,而不是仅添加不填充。
    • @KiranPNair 好呼唤。有人会假设startingAtIndex 意味着从哪里开始填充字符串;但实际上是withString的起始索引。这似乎是最没用的选项,但 Apple 就是这样。
    • 这是使用NSString API,因此,字符计数与 Swift 的字符计数方式相得益彰。
    【解决方案3】:
    extension RangeReplaceableCollection where Self: StringProtocol {
        func paddingToLeft(upTo length: Int, using element: Element = " ") -> SubSequence {
            return repeatElement(element, count: Swift.max(0, length-count)) + suffix(Swift.max(count, count-length))
        }
    }
    

    "123".paddingToLeft(upTo: 5)              //  "  123"
    "123".paddingToLeft(upTo: 5, using: "0")  //  "00123"
    "123".paddingToLeft(upTo: 3, using: "0")  //    "123"
    "$199.99".dropLast(3).paddingToLeft(upTo: 10, using: "_")  //  "______$199"
    

    要复制与 padding(toLength:, withPad:, startingAt:) 相同的行为,我们可以将 rotateTo left 功能添加到 RangeReplaceableCollection

    extension RangeReplaceableCollection {
        func rotatingLeft(positions: Int) -> SubSequence {
            let index = self.index(startIndex, offsetBy: positions, limitedBy: endIndex) ?? endIndex
            return self[index...] + self[..<index]
        }
    }
    

    并按如下方式实现:

    extension RangeReplaceableCollection where Self: StringProtocol {
        func paddingToLeft<S: StringProtocol & RangeReplaceableCollection>(upTo length: Int, with string: S, startingAt index: Int = 0) -> SubSequence {
            let string = string.rotatingLeft(positions: index)
            return repeatElement(string, count: length-count/string.count)
                .joined().prefix(length-count) + suffix(Swift.max(count, count-length))
        }
    }
    

    "123".paddingToLeft(upTo: 10, with: "abc", startingAt: 2)   //  "cabcabc123"
    "123".padding(toLength: 10, withPad: "abc", startingAt: 2)  //  "123cabcabc"
    

    【讨论】:

      【解决方案4】:

      将所有字符串格式代码放入extension 并在任何你想要的地方重复使用。

      extension String {
          func padding(length: Int) -> String {
              return self.stringByPaddingToLength(length, withString: " ", startingAtIndex: 0)
          }
      
          func padding(length: Int, paddingString: String) -> String {
              return self.stringByPaddingToLength(length, withString: paddingString, startingAtIndex: 0)
          }
      }
      
      var str = "str"
      print(str.padding(10)) // "str       "
      print(str.padding(10, paddingString: "+")) // "str+++++++"
      

      【讨论】:

      • 似乎这些函数会从输出中去除换行符。
      【解决方案5】:

      以下两个函数返回一个填充到给定宽度的字符串,左对齐或右对齐。它是纯 Swift 4,没有 NSString,也没有 C 字符串。您可以选择是否截断长于填充宽度的字符串。

      extension String {
          func rightJustified(width: Int, truncate: Bool = false) -> String {
              guard width > count else {
                  return truncate ? String(suffix(width)) : self
              }
              return String(repeating: " ", count: width - count) + self
          }
      
          func leftJustified(width: Int, truncate: Bool = false) -> String {
              guard width > count else {
                  return truncate ? String(prefix(width)) : self
              }
              return self + String(repeating: " ", count: width - count)
          }
      }
      

      【讨论】:

        【解决方案6】:

        这是我的解决方案,专门针对 String,但我确信比我更聪明的人可以使它更通用。

        extension String {
            func frontPadding(toLength length: Int, withPad pad: String, startingAt index: Int) -> String {
                return String(String(self.reversed()).padding(toLength: length, withPad: pad, startingAt: index).reversed())
            }
        }
        

        【讨论】:

          【解决方案7】:

          对于左填充,您可以使用双反转技巧:

          String(String(s.reversed()).padding(toLength: 5, withPad: "0", startingAt: 0).reversed())
          

          当然,你可以把它包装成一个扩展:

          extension String {
              func leftPadding(toLength: Int, withPad: String) -> String {
                  String(String(reversed()).padding(toLength: toLength, withPad: withPad, startingAt: 0).reversed())
              }
          }
          

          【讨论】:

            【解决方案8】:
            import Foundation   // for NSString.padding()
            
            /**
             *  Custom Extension's API
             *  ------------------------------
             *  • str.padEnd(_:_:)
             *  • str.padStart(_:_:)
             *  ------------------------------
             *  • int.padStart(_:_:forceSign:)
             */
            
            extension String {
            
                // str.padEnd(8, "-")
                func padEnd(_ length: Int, _ pad: String) -> String {
                    return padding(toLength: length, withPad: pad, startingAt: 0)
                }
            
                // str.padStart(8, "*")
                func padStart(_ length: Int, _ pad: String) -> String {
                    let str = String(self.reversed())
                    return String(str.padEnd(length, pad).reversed())
                }
            }
            
            extension Int {
            
                // int.padStart(8)
                func padStart(
            
                    _  length: Int,             // total length
                    _     pad: String = "0",    // pad character
                    forceSign: Bool   = false   // force + sign if positive
            
                ) -> String {
            
                    let isNegative = self < 0
                    let n = abs(self)
                    let str = String(n).padStart(length, pad)
            
                    return 
                        isNegative ? "- " + str :
                        forceSign  ? "+ " + str :
                        str
                }
            }
            
            // test run
            let s1 = "abc"
            
            [
                s1.padEnd(15, "*"),                 // abc************
                s1.padStart(15, "*"),               // ************abc
                3.padStart(8, forceSign: true),     // + 00000003
                (-125).padStart(8)                  // - 00000125
            
            ].forEach{ print($0) }
            

            【讨论】:

              猜你喜欢
              • 2010-12-13
              • 1970-01-01
              • 2022-08-05
              • 2015-09-01
              • 2014-11-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多