在用户输入的相关部分和数组之间找到匹配项的最有效方法是什么?

时间:2019-01-25 14:04:57

标签: java groovy

在我的应用程序中,将向用户显示一个列表。然后,他们将输入列表中感兴趣的项目。

我有一个字符串数组,该字符串应该与用户可能写的内容匹配(缩写),如下所示:[“ first”,“ top”,“ second”,“ third”,...,“ bottom “]。

我如何尽可能有效地将其与用户输入的相关部分进行匹配?当用户编写与我的数组完全匹配的内容时,情况很容易,但是在此应用程序中绝对不能保证。即如何有效地将“我的是第一个”或“它的最下面一个”与我的阵列相匹配。

1 个答案:

答案 0 :(得分:0)

与其建议您遍历所有单词并在用户每次输入内容时都对contains进行检查,我建议只循环一次以创建一个匹配的正则表达式,并在每次输入时使用该regex-String用户输入了一些内容。

因此您的数组{"first", "top", "second", "third", "bottom"}将成为以下正则表达式字符串:

"^.*(first|top|second|third|bottom).*$"

这意味着:

^           # Start looking at the start of the String
 .*         # Any amount of random characters (can be none)
   (first|top|second|third|bottom)
            # Followed by one of these words (the `|` are OR-statements)
 .*         # Followed by any mount of random characters again
   $        # Followed by the end of the String

(如果您使用String#matches builtin,则可以删除^$,因为它总是试图隐式地匹配整个给定的String,但是为了澄清起见,我会添加它。)

此后,每次用户使用userInput.matches(regex)输入内容时,都可以使用此正则表达式。

以下是可能的测试代码:

class Main{
  public static void main(String[] a){
    String[] array = {"first", "top", "second", "third", "bottom"};

    // Create the regex-String of the array once:
    String regex = "^.*(";
    for(int i=0; i<array.length; i++){
      regex += array[i];
      if(i < array.length - 1) // All except for the last word in the array:
        regex += "|";
    }
    regex += ").*$";

    // Check all user inputs:
    // TODO: Actually use user inputs instead of this String-array of test cases of course
    for(String userInputTestCase : new String[]{"mine is the first one",
                                                "its the one at the bottom",
                                                "no match",
                                                "top and bottom",
                                                "first"}){
      System.out.println(userInputTestCase + " → " + userInputTestCase.matches(regex));
    }
  }
}

结果:

mine is the first one → true
its the one at the bottom → true
no match → false
top and bottom → true
first → true

因此,如果存在数组中的一个或多个单词,将导致true(包括与最后一个测试用例完全匹配的结果)。

Try it online.


编辑:如果您想匹配字符串,则可以使用带有Pattern.compile(regex).matcher(inputString)的略微修改的正则表达式:

更改这些行:

String regex = "(";   // was `String regex = "^.*(";` above
...
regex += ")";         // was `regex += ").*$";` above

并添加以下内容:

// TODO: Put the imports at the top of the class
// This is done once, just like creating the regex above:
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex);

// The following is done for every user input:
java.util.regex.Matcher matcher = pattern.matcher(userInputTestCase);
java.util.List<String> results = new java.util.ArrayList<>();
while(matcher.find()){
  results.add(matcher.group());
}
System.out.println(userInputTestCase + " → " + results);

Try it online.