我想打印一个字符串列表,使它们都对齐到相同的宽度。
在C语言中,我可以使用类似于 printf("%40s", cstr)
的方式来实现,其中cstr是一个C字符串。
在Swift中,我能想出的最好方法是这样的:
line += String(format: "%40s",string.cStringUsingEncoding(<someEncoding>))
有更好的方法吗?
在 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
方法已被弃用,现在可以使用 prefix
、suffix
或使用范围 Range<String.Index>
对 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))
}
}
}
line += string.padding(toLength: 40, withPad: " ", startingAt: 0)
NSString
提供了stringByPaddingToLength:
方法:
line += string.stringByPaddingToLength(40, withString: " ", startingAtIndex: 0)
返回 "".stringByPaddingToLength(toPad, withString: byString, startingAtIndex: 0) + self;
} - Kiran P NairNSString
API,因此字符计数与 Swift 的字符计数方式不一致。 - Nikolai Ruheextension 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:)相同的行为,我们可以向RangeReplaceableCollection添加rotateToLeft功能。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"
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+++++++"
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)
}
}
对于左填充,您可以使用双重反向技巧:
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())
}
}
这是我的解决方案,特定于 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())
}
}
Swift 5:
我刚刚花了很长时间来解决这个问题,感到非常尴尬。
let short = "ab"
String(repeating: "0", count: 8 - short.count).appending(short)
// 000000ab
这里是左填充
extension String {
func leftPadding(toLength: Int, withPad character: Character) -> String {
if count < toLength {
return String(repeating: character, count: toLength - count) + self
} else {
return self
}
}
}
结果
"234".leftPadding(toLength: 1, withPad: "0") // 234
"234".leftPadding(toLength: 2, withPad: "0") // 234
"234".leftPadding(toLength: 3, withPad: "0") // 234
"234".leftPadding(toLength: 4, withPad: "0") // 0234
"234".leftPadding(toLength: 5, withPad: "0") // 00234
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) }
Foundation
方法padding:toLength:
允许填充超过一个字符。但是这个答案失去了这个功能。 - Zonker.in.Geneva