假设我有这样的代码行:
log.info(f"$name%-20s $amt%7.2f")
我想要做的是使20
(name
的宽度)本身可以被参数化。我该怎么办?
如果我还想同时设置7.2
的{{1}}宽度怎么办?有可能吗?
[编辑:我希望将amt
和20
之类的变量放入变量中,以便不会将它们硬编码为格式字符串。]
我已经尝试过直接使用7.2
,但似乎我不明白正在发生什么宏扩展:
StringContext
答案 0 :(得分:1)
您离真相不远:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace PTS.Models
{
public class Talk
{
[Key]
public int PubId { get; set; }
public string Title { get; set; }
public string Category { get; set; }
}
}
产量:
val amt= 1234.1234d
val name = "James"
println(f"|$name%20s $amt%7.2f|")
关于将20和7.2作为参数传递:模板可以生成为:
| James 1234,12|
产生:
val len = 20
val prec = 7.2
val template = s"$$name%${len}s $$amt%${prec}f"
但是字符串内插似乎并不是解决方案,因为即使将其插入到StringContext中,它也是在编译时完成的,然后
$name%20 $amt%7.2f
产生s"$template
。
我想我可以使用另一种语言
答案 1 :(得分:1)
您可以实现自己的StringContext
注意:# I think '.rxt' is a typo for '.txt'
def recursive_unlink(dirname):
for entry in os.scandir(dirname):
if entry.is_dir():
recursive_unlink(os.path.abspath(entry))
elif entry.name.endswith('.txt'):
os.unlink(os.path.abspath(entry))
recursive_unlink('h:')
为s"a=${a},b=${b}"
StringContext("a=",",b=").s(a,b)
//测试
case class Format(t: String)
// this implement is not type safe in Compile time,
implicit class MyFormat(val sc: StringContext) {
def myFormat(args: Any*) = {
val partIter = sc.parts.iterator
var stringFormatArgs = List.empty[Object]
val sb = new StringBuilder(partIter.next())
def impl(list: List[Any]): Unit = {
list match {
case (_: Format) :: tail =>
throw new Exception("")
case (any: Object) :: (format: Format) :: tail =>
sb.append(partIter.next()).append(format.t).append(partIter.next())
stringFormatArgs = any :: stringFormatArgs
impl(tail)
case (any: Any) :: tail =>
sb.append(any.toString).append(partIter.next())
impl(tail)
case Nil =>
}
}
impl(args.toList)
String.format(sb.toString(), stringFormatArgs.reverse: _*)
}
}
答案 2 :(得分:1)
您可以分为两个部分。
val name = "Jan"
val nLen = -10 //name length
val amt = 1.1
val ff = 5.3 //float format
s"%${nLen}s".format(name) + s"%${ff}f".format(amt)
//res0: String = Jan 1.100
或一次通过。
s"%${nLen}s%${ff}f".format(name, amt)
//res1: String = Jan 1.100