在Python中,格式化字符串时,我可以按名称而不是按位置填充占位符,如下所示:
print "There's an incorrect value '%(value)s' in column # %(column)d" % \
{ 'value': x, 'column': y }
我想知道这在Java中是否可能(希望没有外部库)?
在Python中,格式化字符串时,我可以按名称而不是按位置填充占位符,如下所示:
print "There's an incorrect value '%(value)s' in column # %(column)d" % \
{ 'value': x, 'column': y }
我想知道这在Java中是否可能(希望没有外部库)?
当前回答
我是一个小型库的作者,它可以做你想要的:
Student student = new Student("Andrei", 30, "Male");
String studStr = template("#{id}\tName: #{st.getName}, Age: #{st.getAge}, Gender: #{st.getGender}")
.arg("id", 10)
.arg("st", student)
.format();
System.out.println(studStr);
或者你可以串起参数:
String result = template("#{x} + #{y} = #{z}")
.args("x", 5, "y", 10, "z", 15)
.format();
System.out.println(result);
// Output: "5 + 10 = 15"
其他回答
另一个Apache Common StringSubstitutor的简单命名占位符的例子。
String template = "Welcome to {theWorld}. My name is {myName}.";
Map<String, String> values = new HashMap<>();
values.put("theWorld", "Stackoverflow");
values.put("myName", "Thanos");
String message = StringSubstitutor.replace(template, values, "{", "}");
System.out.println(message);
// Welcome to Stackoverflow. My name is Thanos.
在编写本文时,Java中还没有内置任何东西。我建议编写自己的实现。我的偏好是一个简单流畅的构建器接口,而不是创建一个映射并将其传递给函数——你最终会得到一个漂亮的连续代码块,例如:
String result = new TemplatedStringBuilder("My name is {{name}} and I from {{town}}")
.replace("name", "John Doe")
.replace("town", "Sydney")
.finish();
下面是一个简单的实现:
class TemplatedStringBuilder {
private final static String TEMPLATE_START_TOKEN = "{{";
private final static String TEMPLATE_CLOSE_TOKEN = "}}";
private final String template;
private final Map<String, String> parameters = new HashMap<>();
public TemplatedStringBuilder(String template) {
if (template == null) throw new NullPointerException();
this.template = template;
}
public TemplatedStringBuilder replace(String key, String value){
parameters.put(key, value);
return this;
}
public String finish(){
StringBuilder result = new StringBuilder();
int startIndex = 0;
while (startIndex < template.length()){
int openIndex = template.indexOf(TEMPLATE_START_TOKEN, startIndex);
if (openIndex < 0){
result.append(template.substring(startIndex));
break;
}
int closeIndex = template.indexOf(TEMPLATE_CLOSE_TOKEN, openIndex);
if(closeIndex < 0){
result.append(template.substring(startIndex));
break;
}
String key = template.substring(openIndex + TEMPLATE_START_TOKEN.length(), closeIndex);
if (!parameters.containsKey(key)) throw new RuntimeException("missing value for key: " + key);
result.append(template.substring(startIndex, openIndex));
result.append(parameters.get(key));
startIndex = closeIndex + TEMPLATE_CLOSE_TOKEN.length();
}
return result.toString();
}
}
不幸的是,答案是否定的。然而,你可以非常接近一个合理的语法:
"""
You are $compliment!
"""
.replace('$compliment', 'awesome');
它比String更具可读性和可预测性。至少是格式!
你可以使用StringTemplate库,它提供了你想要的和更多。
import org.antlr.stringtemplate.*;
final StringTemplate hello = new StringTemplate("Hello, $name$");
hello.setAttribute("name", "World");
System.out.println(hello.toString());
谢谢你的帮助!使用所有的线索,我写了一个例程来做我想要的——使用字典的类似python的字符串格式化。因为我是Java新手,任何提示都是感激的。
public static String dictFormat(String format, Hashtable<String, Object> values) {
StringBuilder convFormat = new StringBuilder(format);
Enumeration<String> keys = values.keys();
ArrayList valueList = new ArrayList();
int currentPos = 1;
while (keys.hasMoreElements()) {
String key = keys.nextElement(),
formatKey = "%(" + key + ")",
formatPos = "%" + Integer.toString(currentPos) + "$";
int index = -1;
while ((index = convFormat.indexOf(formatKey, index)) != -1) {
convFormat.replace(index, index + formatKey.length(), formatPos);
index += formatPos.length();
}
valueList.add(values.get(key));
++currentPos;
}
return String.format(convFormat.toString(), valueList.toArray());
}