2014-11-24 20 views
4

我正在寻找最佳方法来检查一个字符串是否包含关键字列表中的子字符串。如何检查一个字符串是否有一个来自列表的子字符串?

例如,我创建了一个列表如下:

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

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

字符串s1为从关键字“玛丽”,但字符串s2没有它。所以,我想定义一个方法:

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

containsAKeyword(s1, keywords)将返回true,但containsAKeyword(s2, keywords)将返回false。即使只有一个子字符串匹配,我也可以返回true。我知道我可以迭代关键字列表并在列表中的每个项目上调用str.contains(),但我想知道是否有更好的方法来遍历整个列表(避免O(n)复杂性),还是Java为此提供了任何内置方法。

+0

你可以找到你可以在这里字符串调用方法:https://docs.oracle.com/javase/7/docs/api/java/lang/String.html我发现它非常有帮助的,通过看所有由String类中的方法定义的标准功能。 – Joop 2014-11-24 17:36:55

回答

6

我会推荐迭代整个列表。值得庆幸的是,你可以使用增强的for循环:

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

编辑知识,你必须以某种迭代列表。想一想,你怎么知道列表中包含哪些元素而不经过它?

EDIT 2

我可以看到快速运行的迭代的唯一方法就是做以上。按照设计的方式,一旦找到匹配项,它就会提前中断,而不会进一步搜索。您可以在循环结束时将您的返回false语句放入,因为如果您检查完整个列表而没有找到匹配项,则显然没有任何匹配项。下面是一些更详细代码:

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

只是出于好奇,为什么你添加编辑您的文章?我的意思是,如果将其与本文的未来相比较,最后10分钟只是一小段时间。未来,人们可能会发现编辑的额外好处非常小。就是想。 – Joop 2014-11-24 17:40:35

+1

你是对的,有时我也怀疑自己。但是,我添加(我相信)是有用的,并且相关信息比最初有用的信息更有帮助。把大胆的**编辑**块可能只是出于习惯。我的意思是,我*正在编辑,对吧? – AdamMc331 2014-11-24 17:43:34

+1

@Joop不是你问这部分,但我觉得编辑2很重要,因为它解决了更多OP关于解决方案复杂性的问题。虽然这仍然是O(n),但我想要解决可能会缩短迭代的方式。 – AdamMc331 2014-11-24 17:44:51

0

我想你应该检查存在的方法在String类:

String s1 = "mary is a good girl"; 
if(s1.contains("mary") 
{ 
    //Success 
} 

如果你想提高性能,也许你可以先拆分句子,然后计算所有字符的总和[ASCII值]每个单词[我们称之为散列值]并为它们中的每一个维护一个单独的存储桶(可能是数组),现在当您获取关键字值时,首先找到它的散列值并访问该数组,然后使其更加高效,他们的长度,然后匹配字符串。

希望有帮助!

+0

您需要检查'关键字'列表中所有单词的字符串,而不仅仅是一个。 – csmckelvey 2014-11-24 17:29:22

+0

是的。这是我的想法。我想知道在时间复杂性方面我能做得比这更好。 – 2014-11-24 17:30:03

+0

然后,你将不得不通过关键字列表循环我猜:) – 2014-11-24 17:30:10

0

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

2

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

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

    return false; 
} 
+0

我不知道为什么我对这个问题有一个低估? – 2014-11-24 17:39:16

+0

这不是我,他们逆转了它,但可能是因为你之前有一个逻辑错误。但是,看起来你找到了它。 – AdamMc331 2014-11-24 17:48:32

1

下面是解

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

在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 
0

根据列表的大小,我会建议使用火柴()方法的字符串。 String.matches需要一个正则表达式的说法是,较小的列表,你可以sinply建立一个正则表达式和评价它:

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

这应该打印出“真”。

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

相关问题