Java:如何根据提供的模式从字符串中提取值并将其填充到Map中?

时间:2019-03-19 18:31:32

标签: java algorithm

我有2个字符串,一个是包含参数的模式,另一个是标题。

我想从标题中提取参数值,然后根据提供的模式将其存储到Map中。模式中的参数以$开头。

示例1:

pattern = "home/$service/$source-$metadataId"
title = "home/serviceA/test-ABC"

然后输出应该是具有所有以下键值对的映射:

service = serviceA
source = test
metadataId = ABC

示例2:

pattern = "home/$service/$source/$region/$year/$month/$day-$metadataId"
title = "home/serviceA/test/NA/2019/3/3-ABC"

然后输出应该是具有所有以下键值对的映射:

service = serviceA
source = test
region = NA
year = 2019
month = 3
day = 3
metadataId = ABC

请让我知道是否有任何库可以用Java做到这一点,或者您将如何用普通Java实现它。

注意:

  1. 参数名称不包含任何特殊字符。 (例如: 标点符号)
  2. 所有参数名称均以$
  3. 开头

5 个答案:

答案 0 :(得分:1)

我不知道任何图书馆。此问题在某些情况下非常具体。但是您可以编写自己的库来处理更多类似情况。这是一个Java小程序,适用于您描述的所有情况(可以进一步扩展)。希望它能给您一些想法。

    String pattern = "home/$service/aaa/$source-$metadataId";
    String title = "home/serviceA/aaa/test-ABC";

    String patternNew = pattern.replaceAll("/\\$|-\\$", "/");

    // assuming both the strings contain same number of tokens.
    String[] keyTokens = (patternNew).split("/|-");
    String[] valueTokens = (title).split("/|-");

    Map<String, String> map = new HashMap<String, String>();

    for (int n = 1; n < keyTokens.length; n++) {
        String key = (keyTokens[n]);
        String value = (valueTokens[n]);

        if(key.equals(value))
            continue;

        map.put(key, value);
    }

    for (String name : map.keySet()) {
        System.out.print(name);
        System.out.print(" = " + map.get(name));
        System.out.println();
    }

答案 1 :(得分:0)

String[] p = pattern.split("/\\$|-");
String[] t = titlesplit("/|-");

 Map<String, String> map = new HashMap<>();
 for(int i=1; i<t.length; i++){
       map.put(p[i], t[i]);
  }

答案 2 :(得分:0)

  1. 使用类似于\$(\w+)的正则表达式将模式分为文字块和占位符名称。对于第一个示例,您将获得以下文字块:"home/""/""-"""(最后一块是空字符串),以及以下占位符名称:{ {1}},"service""source"
  2. 现在,您可以像这样"metadataId"从文字块构造正则表达式。不要忘记正确引用文字块。
  3. 应用此正则表达式并获取捕获的组的值:home/(.*)/(.*)-(.*)"serviceA""test"
  4. 将步骤1中收集的地图占位符名称与步骤3中获得的捕获组值合并。

答案 3 :(得分:0)

假设参数 values (不仅仅是名称)只能包含文字字符,您可以这样做:

String pattern = "home/$service/$source/$region/$year/$month/$day-$metadataId";
String title = "home/serviceA/test/NA/2019/3/3-ABC";
String regex = "\\Q" + pattern.replaceAll("\\$(\\w+)", "\\\\E(?<$1>\\\\w+)\\\\Q") + "\\E";
Matcher m = Pattern.compile(regex).matcher(title);
if (m.find()) {
    Map<String, String> map = getNamedGroupCandidates(regex).stream().collect(Collectors.toMap(Function.identity(), m::group));
    System.out.println(map);
}

getNamedGroupCandidates来自此post的地方:

private static Set<String> getNamedGroupCandidates(String regex) {
    Set<String> namedGroups = new TreeSet<>();

    Matcher m = Pattern.compile("\\(\\?<([a-zA-Z][a-zA-Z0-9]*)>").matcher(regex);

    while (m.find()) {
        namedGroups.add(m.group(1));
    }

    return namedGroups;
}

我基本上将您的“模式”转换为带有命名组的正则表达式。然后,我获取所有组名并使用它们来获取捕获的值。最后,我将所有这些放到一张地图中。

答案 4 :(得分:0)

import java.util.*;
import java.io.*;
public class Solution {
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String pattern = br.readLine();
        String title = br.readLine();
        System.out.println(parseString(pattern,title).toString());
    }   

    private static Map<String,String> parseString(String pattern,String title){
        Map<String,String> map = new HashMap<>();

        String[] pat_tokens = pattern.split("/");
        String[] title_tokens = title.split("/");;

        for(int i=0;i<pat_tokens.length;++i){
            String[] sub_tokens = pat_tokens[i].split("\\-");
            String[] title_sub_tokens = title_tokens[i].split("\\-");
            for(int j=0;j<sub_tokens.length;++j){
                if(sub_tokens[j].charAt(0) != '$') continue;
                map.put(sub_tokens[j],title_sub_tokens[j]);
            }
        }       

        return map;
    }
}

好吧,您可以仅基于/-拆分单个令牌的字符串。如果字符串的起始字符不是$,则它不是您希望将其包含在映射中的键。