在Python中,格式化字符串时,我可以按名称而不是按位置填充占位符,如下所示:

print "There's an incorrect value '%(value)s' in column # %(column)d" % \
  { 'value': x, 'column': y }

我想知道这在Java中是否可能(希望没有外部库)?


当前回答

jakarta commons lang的StrSubstitutor是一种轻量级的实现方法,前提是您的值已经被正确格式化。

http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/text/StrSubstitutor.html

Map<String, String> values = new HashMap<String, String>();
values.put("value", x);
values.put("column", y);
StrSubstitutor sub = new StrSubstitutor(values, "%(", ")");
String result = sub.replace("There's an incorrect value '%(value)' in column # %(column)");

上述结果为:

“第2列中的“1”值不正确”

当使用Maven时,您可以将此依赖项添加到pom.xml:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

其他回答

我最终得到了下一个解决方案: 使用substitute()方法创建类templatessubstitute,并使用它格式化输出 然后创建一个字符串模板,并用值填充它

import java.util.*;
public class MyClass {

    public static void main(String args[]) {
    String template = "WRR = {WRR}, SRR = {SRR}\n" +
                      "char_F1 = {char_F1}, word_F1 = {word_F1}\n";
    
    Map<String, Object> values = new HashMap<>();
    values.put("WRR", 99.9);
    values.put("SRR", 99.8);
    values.put("char_F1", 80);
    values.put("word_F1", 70);
    
    String message = TemplateSubstitutor.substitute(values, template);
    
    System.out.println(message);
    }
}

class TemplateSubstitutor {
    public static String substitute(Map<String, Object> map, String input_str) {
        String output_str = input_str;
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            output_str = output_str.replace("{" + key + "}", String.valueOf(value));
        }
        return output_str;
    }
    
}

你可以在字符串助手类上有这样的东西

/**
 * An interpreter for strings with named placeholders.
 *
 * For example given the string "hello %(myName)" and the map <code>
 *      <p>Map<String, Object> map = new HashMap<String, Object>();</p>
 *      <p>map.put("myName", "world");</p>
 * </code>
 *
 * the call {@code format("hello %(myName)", map)} returns "hello world"
 *
 * It replaces every occurrence of a named placeholder with its given value
 * in the map. If there is a named place holder which is not found in the
 * map then the string will retain that placeholder. Likewise, if there is
 * an entry in the map that does not have its respective placeholder, it is
 * ignored.
 *
 * @param str
 *            string to format
 * @param values
 *            to replace
 * @return formatted string
 */
public static String format(String str, Map<String, Object> values) {

    StringBuilder builder = new StringBuilder(str);

    for (Entry<String, Object> entry : values.entrySet()) {

        int start;
        String pattern = "%(" + entry.getKey() + ")";
        String value = entry.getValue().toString();

        // Replace every occurence of %(key) with value
        while ((start = builder.indexOf(pattern)) != -1) {
            builder.replace(start, start + pattern.length(), value);
        }
    }

    return builder.toString();
}

截至2022年,最新的解决方案是Apache Commons Text StringSubstitutor

医生说:

// Build map
 Map<String, String> valuesMap = new HashMap<>();
 valuesMap.put("animal", "quick brown fox");
 valuesMap.put("target", "lazy dog");
 String templateString = "The ${animal} jumped over the ${target} ${undefined.number:-1234567890} times.";

 // Build StringSubstitutor
 StringSubstitutor sub = new StringSubstitutor(valuesMap);

 // Replace
 String resolvedString = sub.replace(templateString)

;

我试了一下

public static void main(String[] args) 
{
    String rowString = "replace the value ${var1} with ${var2}";
    
    Map<String,String> mappedValues = new HashMap<>();
    
    mappedValues.put("var1", "Value 1");
    mappedValues.put("var2", "Value 2");
    
    System.out.println(replaceOccurence(rowString, mappedValues));
}

private static  String replaceOccurence(String baseStr ,Map<String,String> mappedValues)
{
    for(String key :mappedValues.keySet())
    {
        baseStr = baseStr.replace("${"+key+"}", mappedValues.get(key));
    }
    
    return baseStr;
}

不幸的是,答案是否定的。然而,你可以非常接近一个合理的语法:

"""
   You are $compliment!
"""
.replace('$compliment', 'awesome');

它比String更具可读性和可预测性。至少是格式!