Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:在字符串中匹配短语_Java_Database_Matching_Phrase - Fatal编程技术网

Java:在字符串中匹配短语

Java:在字符串中匹配短语,java,database,matching,phrase,Java,Database,Matching,Phrase,我在数据库中有一个短语列表(短语可能由一个或多个单词组成)和一个输入字符串。我需要找出哪些短语出现在输入字符串中 有没有一种在Java中执行这种匹配的有效方法 下面是一个使用java的解决方案。由于您没有对使用的字符串进行任何指定,所以我考虑一个通用示例< /P> Pattern p = Pattern.compile("cat"); // Create a matcher with an input string Matcher m = p.matcher("one cat,"

我在数据库中有一个短语列表(短语可能由一个或多个单词组成)和一个输入字符串。我需要找出哪些短语出现在输入字符串中


有没有一种在Java中执行这种匹配的有效方法

下面是一个使用java的解决方案。由于您没有对使用的字符串进行任何指定,所以我考虑一个通用示例< /P>
Pattern p = Pattern.compile("cat");
        // Create a matcher with an input string
Matcher m = p.matcher("one cat," +" two cats in the yard");
boolean b = m.matches();  // Should return true
希望有帮助

参考:

检查准备好的语句是否适合数据库,并且重复调用的速度更快,因此如果您有多个输入,它仍然应该是快速的,在循环中执行


当然,您可以将所有短语加载到RAM和地图中。准备缓慢,如果您有多个调用,而不仅仅是一个输入,可能会更快。但是数据库通常是非常高效的搜索工具

您可以将数据库中的搜索短语组织成一个基于公共开头的树。然后,您可以逐个字符地分析字符串,以尝试匹配该树的节点

一个快速破解方法是:

  • 基于组合短语构建regexp
  • 构造一个集合,列出迄今为止尚未匹配的短语
  • 反复运行
    find
    ,直到找到所有短语或输入结束,从要查找的剩余短语集中删除匹配项
  • 这样,不管您提供了多少短语,输入只被遍历一次。如果regexp编译器为多个备选方案生成一个有效的匹配器,这将产生良好的性能。然而,这在很大程度上取决于短语和输入字符串,以及Java正则表达式引擎的质量

    示例代码(已测试,但未针对性能进行优化或分析):

    public静态布尔hasallphrasesinput(列出短语、字符串输入){
    Set phrasetofind=newhashset();
    StringBuilder sb=新的StringBuilder();
    for(字符串短语:短语){
    如果(sb.length()>0){
    某人附加(“|”);
    }
    某人附加(句型、引语(短语));
    短语stofind.add(短语.toLowerCase());
    }
    Pattern=Pattern.compile(sb.toString(),Pattern.CASE不区分大小写);
    Matcher Matcher=pattern.Matcher(输入);
    while(matcher.find()){
    短语stofind.remove(matcher.group().toLowerCase());
    if(phrasesToFind.isEmpty()){
    返回true;
    }
    }
    返回false;
    }
    
    一些警告:

    • 上面的代码将短语匹配为单词的子字符串。如果只有完整的单词匹配,则需要将单词边界(“\b”)添加到生成的正则表达式中
    • 如果某些短语可能是其他短语的子字符串,则必须修改代码
    • 如果需要匹配非ASCII文本,则应添加regexp选项
      Pattern.UNICODE\u CASE
      ,并使用合适的
      Locale
      调用
      toLowerCase(Locale)
      ,而不是
      toLowerCase()

    您有短语或输入字符串的示例吗?许多解决方案可以考虑使用java或SQLAn,例如“私募股权”和“软件”。假设输入字符串是“美国私人股本公司被认为准备对这家英国软件集团进行每股425-450便士的出价,该集团本周透露,它已收到一份有关可能收购的询价。”对于这两个短语,我需要对字符串中的存在进行肯定的回答。席:我可能会考虑像AHO Cracask或后缀树这样的数据结构。java和sqlWell中都没有直接的解决方案,我认为应该是m.find()而不是m.matches。但是,我不认为这是String,Cube(),作为一个合适的解决方案。我的数据库里有大约1000个短语。因此,对于每一个短语,我都必须再次调用这些方法。我认为调用String.contains()或Matcher.find()1000次是没有效率的。我认为使用String.contains()不会有性能问题。从数据库中提取1000个匹配的单词很可能比循环使用它们并将它们与字符串进行比较要慢。我用1000个搜索词和字符串尝试了你的短语。包含,用了1毫秒。哎呀!我刚刚意识到@Amine在评论中提到了这个算法。+1感谢你费劲写了一些长而有信息的东西。谢谢@markusk。虽然这不是我需要解决的确切问题,但我得到了这个想法并实施了它。谢谢@markusk!
    sql = "SELECT phrase " + 
      " FROM phrases " + 
      " WHERE phrase LIKE $1";     
    PreparedStatement pstmt =  conn.prepareStatement (sql);
    // probably repeated, if more than one input:
    pstmt.setString (1, "%" + input + "%");
    ResultSet rs = pstmt.executeQuery ();
    
    public static boolean hasAllPhrasesInInput(List<String> phrases, String input) {
        Set<String> phrasesToFind = new HashSet<String>();
        StringBuilder sb = new StringBuilder();
        for (String phrase : phrases) {
            if (sb.length() > 0) {
                sb.append('|');
            }
            sb.append(Pattern.quote(phrase));
            phrasesToFind.add(phrase.toLowerCase());
        }
        Pattern pattern = Pattern.compile(sb.toString(), Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(input);
        while (matcher.find()) {
            phrasesToFind.remove(matcher.group().toLowerCase());
            if (phrasesToFind.isEmpty()) {
                return true;
            }
        }
        return false;
    }