检测两个字符串是否只包含相同的单词

时间:2013-02-25 18:17:35

标签: java regex performance

以下方法完成了这项工作,但效率不高。

有人知道更优雅的解决方案吗?

我已经摸不着这样的东西但到目前为止没有运气:/ ^(foo | bar | [[:space:] [:punct:]])+ $ /

static public boolean matchTitle(String title, String title2) {

    Scanner scanner1 = new Scanner(title);
    Scanner scanner2 = new Scanner(title2);
    String searchTitle = title2;
    boolean match = false;
    int i = 0;
    while(i < 2){
        if(i == 1){
            scanner1 = new Scanner(title2);
            scanner2 = new Scanner(title);
            searchTitle = title;
        }

        // breaks into words
        while (scanner1.hasNext()){
            match = false;

            String token = scanner1.next();
            scanner2 = new Scanner(searchTitle);
            while (scanner2.hasNext() && !match){
                String token2 = scanner2.next();
                if(token.equals(token2)){
                    // if the words match
                    match = true;
                }
            }
            if(!match){ // we have a word that didn't match any words in the second title
                return false;
            }
        }
        i++;
    }
    return true;
}

示例

(“此处类似的词”,“此处类似的词”)// true

(“此处类似的词”,“此处类似的词语”)// true

(“这里类似的词”,“这里的相似词语不同”)//假

2 个答案:

答案 0 :(得分:3)

我会选择更简单的版本:

List<String> words1 = Arrays.asList(title.split(" "));
List<String> words2 = Arrays.asList(title2.split(" "));

return words1.containsAll(words2) &&
       words2.containsAll(words1);

假设:

  • title和title2为非null
  • space是唯一的分隔符
  • 如果一个字符串包含n次相同的单词,另一个字符串也必须包含该单词n次

修改

您的编辑显示重复没问题。在这种情况下,您可以使用集合而不是列表:

Set<String> words1 = new HashSet<String> (Arrays.asList(title.split(" ")));
Set<String> words2 = new HashSet<String> (Arrays.asList(title2.split(" ")));

return words1.size() == words2.size() && words1.containsAll(words2);

注意:如chm052 in his answer所示,在集合的情况下,您可以简单地检查是否相等,忽略顺序(但不在List示例中):

return words1.equals(words2);

答案 1 :(得分:1)

你要问的是第一个字符串中的单词集等于第二个字符串中的单词集。毕竟,根据定义,你想要忽略的关于字符串(单词顺序和重复单词)的内容不存在于集合中。

所以,你需要

Set<String> words1 = new HashSet<String> (Arrays.asList(title.split(" ")));
Set<String> words2 = new HashSet<String> (Arrays.asList(title2.split(" ")));

return words1.equals(words2);

编辑:

正如assylias指出的那样,如果切换使用equals方法而不是size和containsAll方法,那么功能上没有太大的变化,但是在阅读代码时更容易理解。以这种方式将此方法与集合类解耦也可能是更好的OO实践;那么,例如,如果在Java集合类中实现了更好的查找深度集合相等的算法,那么您将可以使用该改进。

奖金第二次编辑:

如果有人对这个评论主题感到困惑,那就是关于assylias之前的回答(无论是否适用于所有情况):

List<String> words1 = Arrays.asList(title.split(" "));
List<String> words2 = Arrays.asList(title2.split(" "));
return words1.size() == words2.size() && words1.containsAll(words2);