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

Java:如何根据提供的模式从字符串中提取值并将其填充到映射中?,java,algorithm,Java,Algorithm,我有两个字符串,一个是包含参数的模式,另一个是标题 我想从标题中提取参数值,并根据提供的模式将它们存储到映射中。模式中的参数以$作为前缀 例1: pattern = "home/$service/$source-$metadataId" title = "home/serviceA/test-ABC" 然后,输出应该是具有以下所有键值对的映射: service = serviceA source = test metadataId = ABC service = serviceA sourc

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

我想从标题中提取参数值,并根据提供的模式将它们存储到映射中。模式中的参数以$作为前缀

例1:

pattern = "home/$service/$source-$metadataId"
title = "home/serviceA/test-ABC"
然后,输出应该是具有以下所有键值对的映射:

service = serviceA
source = test
metadataId = ABC
service = serviceA
source = test
region = NA
year = 2019
month = 3
day = 3
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
metadataId = ABC
service = serviceA
source = test
region = NA
year = 2019
month = 3
day = 3
metadataId = ABC
请让我知道是否有任何库可以在Java中实现这一点,或者您将如何在普通Java中实现这一点

注:

  • 参数名称不包含任何特殊字符。(例如: (标点符号)
  • 所有参数名称都以$
  • String[]p=pattern.split(“/\\$\”);
    字符串[]t=标题拆分(“/|-”);
    Map Map=newhashmap();
    对于(int i=1;i
    
  • 使用类似于
    \$(\w+)
    的正则表达式将模式拆分为文本块和占位符名称。对于第一个示例,您将获得以下文本块:
    “home/”
    “/”
    “-”
    (最后一个块是空字符串),以及以下占位符名称:
    “service”
    “源代码”
    “元数据ID”
  • 现在,您可以从如下文本块构造正则表达式:
    home/(.*)/(.*)-(.*)
    。不要忘记正确引用文本块
  • 应用此正则表达式并获取捕获组的值:
    “serviceA”
    “test”
    “ABC”
  • 将在步骤1中收集的地图占位符名称与在步骤3中获得的捕获组值合并为地图占位符名称

  • 假设参数值(不仅仅是名称)只能包含单词字符,则可以执行以下操作:

    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);
    }
    

    我基本上转换了你的“模式”在一个带有命名组的正则表达式中。然后,我获取所有组名并使用它们获取捕获的值。最后,我将所有这些放在一个映射中。

    据我所知,没有库。这个问题非常特定于某些情况。但是,您可以编写自己的库来处理更多类似的情况。下面是一个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();
        }
    
    String pattern=“home/$service/aaa/$source-$metadataId”;
    字符串title=“home/serviceA/aaa/testabc”;
    String patternNew=pattern.replaceAll(“/\\$”-\\$”,“/”;
    //假设两个字符串包含相同数量的令牌。
    字符串[]keyTokens=(patternNew).split(“/|-”);
    字符串[]valueTokens=(title).split(“/|-”);
    Map Map=newhashmap();
    for(int n=1;n
    导入java.util.*;
    导入java.io.*;
    公共类解决方案{
    公共静态void main(字符串[]args)引发IOException{
    BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
    字符串模式=br.readLine();
    字符串标题=br.readLine();
    System.out.println(parseString(pattern,title.toString());
    }   
    私有静态映射解析字符串(字符串模式、字符串标题){
    Map Map=newhashmap();
    String[]pat_tokens=pattern.split(“/”);
    String[]title_tokens=title.split(“/”);;
    
    对于(int i=0;我不知道有哪一个库可以解析这样的信息。可能您必须手动解析。最好放弃第一个关于推荐库的请求。这些问题在这里完全脱离主题。我也不知道这个问题的现有解决方案。对于“如何解决”这个问题,这取决于您的“模式”的真实性质。意思:有两个例子很好,但您可能需要一个解析器和一个引擎,该引擎接受您的“模式”并将其应用于文本输入。您最好从明确定义这些模式的确切性质开始。因此,通过“不包含任何特殊字符”你的意思是参数名称只包含ASCII字母和数字?我们只看到你的要求,你的尝试也会很好(代码片段)。有没有答案回答你的问题?如果是这样,请考虑接受答案。我认为,这相当接近正确,对于“普通java”。我认为,尽管你必须跳过。“home”字符串,这意味着检查您的参数是否以“$”开头,OP的要求中提到了这一点。它不能处理这种情况:pattern=“home/$service/aaa/$source-$metadataId”和title=“home/serviceA/aaa/test ABC”,因为在这个输入中,模式aaa不是以$开头的。在您所述的问题中(2.所有参数名称都以$开头)。根据您的语句,它应该是$aaa或其他名称。aaa不是一个参数,这与home相同。它只是参数之间的一个常规字符串文字。您希望它通过跳过它来处理“aaa”并跳过“aaa”“值中是否也包含字符串?我明白了。这在您的问题中有点不清楚。我更新了代码。现在应该可以工作了。除非有其他不明确的情况。无论如何,我建议可能为问题添加更多详细信息(更多示例)。这可能是未来读者感兴趣的用例。希望有帮助:)我用修复程序更新了代码。如果您不喜欢密钥名中的
    $
    ,您可以使用substring()将其删除。
    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;
        }
    }