在字符串数组中搜索子字符串的最有效方法

Posted

技术标签:

【中文标题】在字符串数组中搜索子字符串的最有效方法【英文标题】:Most efficient way to search String array for substring 【发布时间】:2012-12-18 09:41:51 【问题描述】:

假设我有一个这样的字符串数组:

0 ["Some plain text"]
1 ["Foobar chicken"]

我想在每个字符串(在数组的每个索引中)搜索特定的子字符串,比如plain,然后在找到子字符串的第一个实例时返回true

最有效的方法是什么?

我知道我可以在 for 循环中执行简单的 break,但我听说有人说在 for 循环中使用 break 是不好的做法。我还听说使用whiledo-while 也不好。

我的实现

这是我使用 break 的简单实现:

for (String[] index : tmpList) 
    retVal = index[2].toLowerCase().contains(keyword);

    if (retVal) // Break when retVal is true
        break;

地点:

tmpListArrayList<String[]> keyword 是我想要找到的

【问题讨论】:

我会使用indexOf(..) 我在使用 break 时看不到任何“坏”。 这些你听到的东西一般来说都是非常愚蠢的。当你找到子字符串时,只需执行一个循环并中断。例如,使用String.contains() 查找子字符串。 为什么 break 是不好的做法?这就像说强制退出循环是一种不好的做法。我可以找到数千种有用的情况。 如果您先分配retval,然后进行测试,我会感觉更好。 【参考方案1】:

我知道 apache-commons 有一个名为 StringUtils 的实用程序类,它可以为您提供优雅的解决方案。

public boolean foo(String[] array, String pattern)
    for(String content : array)
        if(StringUtils.contains(content, pattern)
            return true;
        
    
    return false;

我不喜欢的一点是它只会在第一个找到的实例时返回 true。我不完全确定您要尝试做什么,但如果您不关心数组中与模式不匹配的索引,我建议您使用名为 filter 的高阶函数。

Guava、lambdaJ 和 Apache-Commons 是支持函数式编程的库。

下面是一些应该在 Apache-Commons 中工作的 sudo 代码。

List<String> content = Arrays.asList(strArray);
Predicate matchesPattern = new Predicate("asdf")
    private String pattern;
    public Predicate(String pattern)
        this.pattern = pattern;
    
    @Overload
    public boolean evaluate(Object input)

        if(input instanceOf String)
            StringUtils.contains((String)input, pattern
        
        return false;
    
;

CollectionUtils.filter(content, matchesPattern);

这样做是从列表中删除任何与模式不匹配的字符串。如您所见,声明 Predicate 对象有点冗长。如果您使用 Apache-Commons 或 Guava,它看起来会很相似,但这就是 lambdaJ 的用武之地。

谓词只是接受单个参数并返回布尔值的函数的术语,您可能已经在 Matcher 类中使用过它们。 Hamcrest 有一些最好的 Matcher 库,所以 lambdaJ 只是围绕它构建了一个函数式编程库。它易于使用且可读性强。

【讨论】:

只是一件小事:if(StringUtils.contains(content, pattern) 行的末尾缺少一个括号。顺便说一句,答案很好。【参考方案2】:

我知道我可以在 for 循环中做一个简单的中断,但我听人们说 在 for 循环中使用 break 是不好的做法。

你在哪里找到的?那是完全错误的。 Is it a bad practice to use break in a for loop?

只需使用 for 循环并循环遍历 Strings。使用String#contains 检查String 是否有特定的子字符串。然后将String 存储在一个变量中(如果需要,也可以存储在索引中)和break;

【讨论】:

我从一位教授那里听说。曾经但现在我不确定她是在谈论break 还是goto。无论如何,感谢 SO 链接。 教授建议在学习如何编码时不要使用 break 和 goto,因为他们希望您更多地考虑算法而不是实现。 goto 应该少用,因为它会降低代码的可读性。

以上是关于在字符串数组中搜索子字符串的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章

哪种 C# 数据结构允许最有效地在一对字符串中搜索子字符串?

在 PostgreSQL 列中搜索子字符串

在 MariaDB 中搜索子字符串或单词

使用 objectify 在实体中搜索子字符串

无法从 Ansible 变量中搜索子字符串

在列表中的元素中搜索子字符串并删除该元素