如何检查字符串是不是具有列表中的子字符串?

Posted

技术标签:

【中文标题】如何检查字符串是不是具有列表中的子字符串?【英文标题】:How can I check if a string has a substring from a List?如何检查字符串是否具有列表中的子字符串? 【发布时间】:2015-01-22 12:04:39 【问题描述】:

我正在寻找检查字符串是否包含关键字列表中的子字符串的最佳方法。

例如,我创建一个这样的列表:

List<String> keywords = new ArrayList<>();
keywords.add("mary");
keywords.add("lamb");

String s1 = "mary is a good girl";
String s2 = "she likes travelling";

字符串 s1 有关键字中的“mary”,但字符串 s2 没有。所以,我想定义一个方法:

boolean containsAKeyword(String str, List<String> keywords)

containsAKeyword(s1, keywords) 将返回 true,而 containsAKeyword(s2, keywords) 将返回 false。即使只有一个子字符串匹配,我也可以返回 true。

我知道我可以遍历关键字列表并在列表中的每个项目上调用 str.contains(),但我想知道是否有更好的方法来遍历完整列表(避免 O(n) 复杂性) 或者 Java 是否为此提供了任何内置方法。

【问题讨论】:

您可以在此处找到可以在字符串上调用的方法:docs.oracle.com/javase/7/docs/api/java/lang/String.html 我发现查看 String 类中的方法定义的所有标准功能非常有帮助。 一个重要的评论:想象keywords.add("travel"),是你的函数的结果,第二个短语是true(事实上它只是一个单词的一部分就足够了)或false (只有完整的单词需要验证)。 【参考方案1】:

您可以在哈希图中添加关键字中的所有单词。然后可以对字符串 1 和字符串 2 使用 str.contains 来检查关键字是否可用。

【讨论】:

【参考方案2】:

我建议遍历整个列表。幸运的是,您可以使用增强的 for 循环:

for(String listItem : myArrayList)
   if(myString.contains(listItem))
      // do something.
   

EDIT我的 所知,您必须以某种方式迭代列表。想一想,不经过它怎么知道列表中包含了哪些元素?

编辑 2

我可以看到迭代快速运行的唯一方法是执行上述操作。按照这种设计方式,一旦你找到匹配项,它就会提前中断,而无需进一步搜索。您可以将 return false 语句放在循环结束时,因为如果您检查了整个列表但没有找到匹配项,那么显然没有。下面是一些更详细的代码:

public boolean containsAKeyword(String myString, List<String> keywords)
   for(String keyword : keywords)
      if(myString.contains(keyword))
         return true;
      
   
   return false; // Never found match.

编辑 3

如果您使用的是 Kotlin,则可以使用 any 方法执行此操作:

val containsKeyword = myArrayList.any  it.contains("keyword") 

【讨论】:

只是出于好奇,您为什么要在帖子中添加编辑?我的意思是最后 10 分钟只是一小段时间,如果你将它与这篇文章的未来进行比较的话。将来人们可能会发现编辑的额外好处非常小。只是想知道。 你是对的,有时我也会质疑自己。但是,我正在添加(我相信的)有用且相关的信息,这些信息比原来的信息更有帮助。放置粗体 EDIT 块可能只是出于习惯。我的意思是,我正在进行编辑,对吧? @Joop 不是你问这部分,但我觉得编辑 2 很重要,因为它解决了更多 OP 关于解决方案复杂性的问题。虽然这仍然是 O(n),但我想提出一种可以可能缩短迭代的方法。 确实是你添加的相关信息。通过这种方式,您确实增加了已经阅读您帖子的人也会阅读编辑部分的可能性。尤其是因为帖子在最初的几分钟内产生了很多点击,并且在很短的时间内减少了很多。我正在和自己争论我是否应该这样做。这就是我问的原因。 @Joop 只要您认为可以改进您的问题/答案,就这样做。为什么你应该心甘情愿地支持你知道可以更好的事情?在你所做的每一件事中都有良好的职业道德。没有人第一次就能把事情做得很好,幸运的是,在这里我们可以选择改进和/或纠正我们的错误。【参考方案3】:

遍历关键字列表,如果字符串包含您的关键字,则返回true。否则返回false

public boolean containsAKeyword(String str, List<String> keywords)
    for(String k : keywords)
        if(str.contains(k))
            return true;
    

    return false;

【讨论】:

我不知道为什么我对这个问题投了反对票?【参考方案4】:

解决办法

List<String> keywords = new ArrayList<>();
keywords.add("mary");
keywords.add("lamb");

String s1 = "mary is a good girl";
String s2 = "she likes travelling";
// The function
boolean check(String str, List<String> keywords)
  Iterator<String> it = keywords.iterator();
  while(it.hasNext())
    if(str.contains(it.next()))
       return true;
  
  return false;

【讨论】:

【参考方案5】:

在 JDK8 中你可以这样做:

public static boolean hasKey(String key) 
   return keywords.stream().filter(k -> key.contains(k)).collect(Collectors.toList()).size() > 0;


hasKey(s1); // prints TRUE
hasKey(s2); // prints FALSE

【讨论】:

user.getRooms().stream().anyMatch(room -> room.contains(mem1)) .... IDE 建议【参考方案6】:

根据列表的大小,我建议使用 String 的 matches() 方法。 String.matches 接受一个正则表达式参数,对于较小的列表,您可以简单地构建一个正则表达式并对其进行评估:

String Str = new String("This is a test string");
System.out.println(Str.matches("(.*)test(.*)"));

这应该打印出“真”。

或者你可以使用java.util.regex.Pattern

【讨论】:

【参考方案7】:

现在您可以为此目的使用 Java 8 流:

keywords.stream().anyMatch(keyword -> str.contains(keyword));

【讨论】:

以上是关于如何检查字符串是不是具有列表中的子字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查字符串是不是是字符串列表中项目的子字符串?

如何检查字符串是不是包含 JavaScript 中的子字符串?

如何检查字符串是不是包含 JavaScript 中的子字符串?

如何检查字符串是不是包含 JavaScript 中的子字符串?

如何检查字符串是不是包含 JavaScript 中的子字符串?

如何检查字符串是不是包含Ruby中的子字符串