我有三个字符串,例如“A”,“B”,“C”。 我必须生成串联它们的字符串,只有第二个字符串必须用空格填充给定长度。
这是我在直觉和一般Scala新闻的指导下的第一次尝试:
val s1 = "A"
val s2 = "B"
val s3 = "C"
val padLength = 20
val s = s1 + s2.padTo(padLength, " ") + s3
这是错误的,因为padTo返回一个SeqLike,其toString不返回内部的字符串,而是类似Vector的表示。
在Scala中执行此操作的最佳惯用方法是什么?
答案 0 :(得分:21)
String
可以(通过此处隐式转换为StringOps
)被视为字符的集合,因此您的填充应为:
val s = s1 + s2.padTo(padLength, ' ') + s3 // note the single quotes: a char
在.padTo(padLength, " ")
上拨打String
实际上会返回Seq[Any]
,因为您的序列中包含字符和字符串。
答案 1 :(得分:9)
您没有说是否要向左或向右填充。只需使用格式:
val s = f"$s1%s$s2%20s$s3"
或者,在Scala 2.10之前(或者如果你需要“20”作为参数):
val s = "%s%"+padLength+"s%s" format (s1, s2, s3)
使用负填充向右侧而不是左侧添加填充空间。
答案 2 :(得分:5)
有人应该提一下你应该发出警告:
apm@mara:~$ skala -Ywarn-infer-any
Welcome to Scala version 2.11.0-20130524-174214-08a368770c (OpenJDK 64-Bit Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.
scala> "abc".padTo(10, "*").mkString
<console>:7: warning: a type was inferred to be `Any`; this may indicate a programming error.
val res0 =
^
res0: String = abc*******
请注意,这样做是没有错的(本身)。
也许有一个用例:
scala> case class Ikon(c: Char) { override def toString = c.toString }
defined class Ikon
scala> List(Ikon('#'),Ikon('@'),Ikon('!')).padTo(10, "*").mkString
res1: String = #@!*******
或更好
scala> case class Result(i: Int) { override def toString = f"$i%03d" }
defined class Result
scala> List(Result(23),Result(666)).padTo(10, "---").mkString
res4: String = 023666------------------------
由于这不是您的使用案例,您可能应该询问是否要使用冗长且充满危险的API。
这就是丹尼尔的答案是正确答案的原因。我不确定为什么他的例子中的格式字符串看起来如此可怕,但它通常看起来更加温和,因为在大多数可读字符串中,你只需要在几个地方格式化字符。
scala> val a,b,c = "xyz"
scala> f"$a is followed by `$b%10s` and $c%.1s remaining"
res6: String = xyz is followed by ` xyz` and x remaining
您需要添加虚假格式化程序的一种情况是您需要换行符:
scala> f"$a%s%n$b$c"
res8: String =
xyz
xyzxyz
我认为插补器应该处理f“$ a%n $ b”。哦,等一下,它已经修复了2.11。
scala> f"$a%n$b" // old
<console>:10: error: illegal conversion character
f"$a%n$b"
scala> f"$a%n$b" // new
res9: String =
xyz
xyz
所以现在没有理由不插入。
答案 3 :(得分:2)
这有效:
val s = s1 + s2.padTo(padLength, " ").mkString + s3
但感觉不知何故。
答案 4 :(得分:2)
有formatted
方法可用。例如:
val s = s1 + s2.formatted("%-10s") + s3
以及format
:
val s = s1 + "%-10s".format(s2) + s3
但如果可以直接嵌入padLength
,我只会使用它。
如果它在别处定义(如你的例子中所示),你可以使用padTo
,就像gourlaysama指出的那样。
如果你想“向左打”,你可以使用隐式类:
object Container {
implicit class RichChar(c: Char) {
def repeat(n: Int): String = "".padTo(n, c)
}
implicit class RichString(s: String) {
def padRight(n: Int): String = {
s + ' '.repeat(n - s.length)
}
def padLeft(n: Int): String = {
' '.repeat(n - s.length) + s
}
}
}
object StringFormat1Example extends App {
val s = "Hello"
import Container._
println(s.padLeft(10))
println(s.padRight(10))
}
答案 5 :(得分:1)
s1 + s2 + " "*(padLength - s2.size) + s3
答案 6 :(得分:1)
这值得加入misc重新制定:
scala> val a = "A"; val b="B";val c="C"
a: String = A
b: String = B
c: String = C
scala> b.padTo(10, " ").mkString(a, "", c)
res1: String = AB C
在星期天为教会节省了一些+。
我成为了this really wonky commit开发mkString的信徒。