Извлечение пары ключ-значение из подстроки в строке

#java #regex

Вопрос:

Ниже приведен код :

 import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestCode {

    private Map<String, String> getMappedValues(final String line) {
        final Map<String, String> mappedValues = new HashMap<String, String>();

        final Pattern p = Pattern.compile(""(.*?)"");
        final Matcher m = p.matcher(line);

        while (m.find()) {
            for (String strTemp : m.group().split(",")) {
                String key = strTemp.split("=")[0].replace("$", "").replace(""", "").trim();
                String value = strTemp.split("=")[1].replace(""", "").trim();
                mappedValues.put(key, value);
            }
        }

        return mappedValues;
    }

    public static void main(String args[]) {

        final String str = "aaaa,"$0 = test1, $1 = test2",a,b,c";

        final TestCode testCode = new TestCode();
        Map<String, String> mappedValues = testCode.getMappedValues(str);
        mappedValues.entrySet().forEach(entry -> {
            System.out.println(entry.getKey()   " "   entry.getValue());
        });

    }

}
 

С принтами :

 0 test1
1 test2
 

Строка "$0 = test1, $1 = test2" анализируется из строки

 "aaaa,"$0 = test1, $1 = test2",a,b,c"
 

Затем строка "$0 = test1, $1 = test2" преобразуется в карту, где ключ находится слева = , а значение справа =

Может встречаться переменное количество пар ключ-значение.

Сейчас я просто концентрируюсь на счастливом пути.

Есть ли более чистый метод анализа значений, а не использование :

 String key = strTemp.split("=")[0].replace("$", "").replace(""", "").trim();
String value = strTemp.split("=")[1].replace(""", "").trim();
 

?

Ответ №1:

Поскольку вы уже используете регулярные выражения, вам следует избавиться от всех String.split() s, используя регулярное выражение, которое также захватывает $key = value пары, используя группы захвата подпоследовательностей.

Вот мое регулярное выражение без экранирования для удобства чтения. Обратите внимание на использование (?:) для создания группы без захвата; только num и value $num = value попарно захватываются как подгруппы.

 "$(d )s=s(w )(?:,s$(d )s=s(w ))*"
 

Используя приведенное выше регулярное for выражение, цикл значительно упрощается.

 final Pattern p = Pattern.compile(""\$(\d )\s=\s(\w )(?:,\s\$(\d )\s=\s(\w ))*"");
final Matcher m = p.matcher(line);

while (m.find()) {
    for (int i = 1; i <= m.groupCount(); i  ) {
        mappedValues.put(m.group(i), m.group(  i));
    }
}