如何在另一个字符串中搜索字符串列表?

问题描述 投票:3回答:5

这是一些有效的代码,但看起来不够优雅。在另一个字符串中搜索这些字符串的更好方法是什么?

String AndyDaltonInjury = "broken right thumb";

if (AndyDaltonInjury.toLowerCase().contains("broken") &&
    (AndyDaltonInjury.toLowerCase().contains("knee") ||
    AndyDaltonInjury.toLowerCase().contains("leg")   ||
    AndyDaltonInjury.toLowerCase().contains("ankle") ||
    AndyDaltonInjury.toLowerCase().contains("thumb") ||
    AndyDaltonInjury.toLowerCase().contains("wrist"))) 
{
    System.out.println("Marvin sends in the backup quarterback.");  
}
java string iteration
5个回答
8
投票

使用Set集合及其方法Set::contains insde流分割数组与空格(" ")分隔符:

Set<String> set = new HashSet<>(Arrays.asList("knee", "leg", "ankle", "thumb", "wrist"));

String lower = "broken right thumb".toLowerCase();
String split[] = lower.split(" ");
if (lower.contains("broken") && Arrays.stream(split).anyMatch(set::contains)) {
    System.out.println("Marvin sends in the backup quarterback.");
}

此外,我强烈建议您使用较低的变量名称。


1
投票

作为已经发布的基于Set的解决方案的替代方案(从可见性的角度来看,我发现它更好),这可以使用正则表达式来完成:

final Pattern brokeStuffPattern = Pattern.compile(
    ".*\\bbroken?\\b.*\\b(?:knee|leg|ankle|thumb|wrist)s?\\b.*"
    + "|.*\\b(?:knee|leg|ankle|thumb|wrist)s?\\b.*\\bbroken?\\b.*",
    Pattern.CASE_INSENSITIVE
);
if (brokeStuffPattern.matcher(AndyDaltonInjury).matches()) {
    ...
}

这将解释复数和动词的完美时态,例如如果匹配“断腿”。


0
投票

您可以创建缺少的函数(包含all / any)作为方法,或使用Lambda表示法表达它们:

BiPredicate<String, List<String>> containsAll = (text, words) -> 
    words.stream().allMatch(word -> text.toLowerCase().contains(word));
BiPredicate<String, List<String>> containsAny = (text, words) -> 
    words.stream().anyMatch(word -> text.toLowerCase().contains(word));

if (containsAll.test(AndyDaltonInjury, Arrays.asList("broken")) && 
    containsAny.test(AndyDaltonInjury, Arrays.asList("knee", "leg", "ankle", "thumb", "wrist"))) {
    System.out.println("Marvin sends in the backup quarterback.");
}

0
投票

你可以试试这个:

String test = "broken right thumb";

Predicate << ? super String > machCriteria = s - > Stream.of("knee", "leg", "ankle", "thumb", "wrist").anyMatch(e - > e.equals(s.toLowerCase()));
String result = Pattern.compile(" ").splitAsStream(test).anyMatch(machCriteria) ? "Marvin sends in the backup quarterback." : "";
System.out.println(result);

0
投票

如果您需要检查大量文本中的大量文本,基于哈希的算法可能会为您提供更好的性能。

HashSet将是一个很好的第一次尝试,因为搜索(测试集合中包含的密钥)是否在O(1)和O(n)之间。

但是,我强烈建议考虑使用[Bloom Filter][1]的好处。它可以很好地用作预滤器,因为它可以提供可预测的O(k)性能。由于过滤器的误报率很小,因此您还需要运行第二阶段。

查看Guava BloomFilter以获得良好的实施。

Bloom Filter的另一个好处是它不包含原始数据集,只是一个简化的哈希值,这意味着它的大小是最小的。这意味着它更适合分布式系统,因为它非常有效地复制。在像Apache Spark这样的环境中,您甚至可以将其设置为Broadcast变量,因为一旦生成它通常会在时间上保持不变。

© www.soinside.com 2019 - 2024. All rights reserved.