【问题标题】:Test if a string contains any of the strings from an array测试字符串是否包含数组中的任何字符串
【发布时间】:2012-02-18 00:15:18
【问题描述】:

如何测试一个字符串以查看它是否包含数组中的任何字符串?

而不是使用

if (string.contains(item1) || string.contains(item2) || string.contains(item3))

【问题讨论】:

  • 您是在询问一个字符串是否等于 与数组中的任何字符串,还是包含 数组中的任何字符串?
  • 您想检查数组中的任何字符串是否是您输入字符串的子字符串?或者您想检查您的输入字符串是否 equals 是数组中的字符串之一?你能说得更准确点吗?
  • 包含,因此它需要一行并查看它是否包含列表中的任何单词(存储为字符串数组)

标签: java string if-statement


【解决方案1】:

最简单的方法可能是将数组转换为 java.util.ArrayList。一旦它在数组列表中,您就可以轻松地利用 contains 方法。

public static boolean bagOfWords(String str)
{
    String[] words = {"word1", "word2", "word3", "word4", "word5"};  
    return (Arrays.asList(words).contains(str));
}

【讨论】:

  • 这是不正确的。 OP 询问string 是否包含数组中的任何Strings,而不是数组中的任何Strings 是否包含string
  • @BeauGrantham 我也在想这个,但是 OP 在他们的帖子中使用了.equals(),这非常令人困惑。我认为他们需要编辑他们的问题
  • @BeauGrantham Man 我不能发誓我理解这个问题。也许这个问题需要再澄清一点?
  • 不,这种反向是行不通的,你应该检查字符串是否包含一个给定的值,而不是如果给出的值包含字符串。
  • 问题是相反的
【解决方案2】:

试试这个:

if (Arrays.stream(new String[] {item1, item2, item3}).anyMatch(inputStr::contains))

【讨论】:

  • 问题是相反的:目标字符串是否包含列表的任何字符串。
  • stream()anyMatch() 需要 API 级别 24 或以上
  • @DilankaLaksiri 不是真的,这些方法从 Java 8 开始就已经可用。而最新版本的 Java 是 16,那么您指的“API 级别 24”是什么?
  • @ÓscarLópez 我说的是 Android API 级别。
  • 好的,很好。但这个问题与 Android 无关 :)
【解决方案3】:
if (Arrays.asList(array).contains(string))

【讨论】:

  • 问题是相反的:目标字符串是否包含列表的任何字符串。
【解决方案4】:

您可以像这样使用String#matches 方法:

System.out.printf("Matches - [%s]%n", string.matches("^.*?(item1|item2|item3).*$"));

【讨论】:

    【解决方案5】:

    假设 Strings 是您要在其中搜索的数组,以下内容应该对您有用:

    Arrays.binarySearch(Strings,"mykeytosearch",mysearchComparator);
    

    其中 mykeytosearch 是您要测试是否存在于数组中的字符串。 mysearchComparator - 是用于比较字符串的比较器。

    请参阅Arrays.binarySearch 了解更多信息。

    【讨论】:

    • 应该注意,binarySearch 仅适用于自然排序或通过给定比较器(如果已给出)排序的数组。
    【解决方案6】:

    编辑:这是使用 Java 8 Streaming API 的更新。干净多了。仍然可以与正则表达式结合使用。

    public static boolean stringContainsItemFromList(String inputStr, String[] items) {
        return Arrays.stream(items).anyMatch(inputStr::contains);
    }
    

    此外,如果我们将输入类型更改为 List 而不是数组,我们可以使用 items.stream().anyMatch(inputStr::contains)

    如果您希望返回匹配的字符串,也可以使用.filter(inputStr::contains).findAny()

    重要提示:上述代码可以使用parallelStream() 完成,但大多数情况下这实际上会影响性能。见this question for more details on parallel streaming


    原始答案略过时:

    这是一个(非常基本的)静态方法。请注意,比较字符串区分大小写。使其不区分大小写的原始方法是在输入和测试字符串上调用toLowerCase()toUpperCase()

    如果您需要做比这更复杂的事情,我建议您查看PatternMatcher 类并学习如何做一些正则表达式。一旦理解了这些,就可以使用这些类或 String.matches() 辅助方法。

    public static boolean stringContainsItemFromList(String inputStr, String[] items)
    {
        for(int i =0; i < items.length; i++)
        {
            if(inputStr.contains(items[i]))
            {
                return true;
            }
        }
        return false;
    }
    

    【讨论】:

    • 如何使用正则表达式@gnomed
    • 如何让第一个实现区分大小写?
    • 实现已经区分大小写。我还有关于如何在答案的底部段落中使其不区分大小写的说明。
    • parallelStream 使用的最小批量大小为 1024,它实际上不会并行化小列表。这是一支长枪。
    • @CallumRogers 是的,我有点把它留给人们思考它,但我同意绝大多数情况下它不会有太大的不同(或实际上是有害的)与非-并行流。将尝试在答案中更多地指出这一点。
    【解决方案7】:

    一种更时髦的方法是结合使用 injectmetaClass

    我想说:

    String myInput="This string is FORBIDDEN"
    myInput.containsAny(["FORBIDDEN","NOT_ALLOWED"]) //=>true
    

    方法是:

    myInput.metaClass.containsAny={List<String> notAllowedTerms->
       notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
    }
    

    如果您需要 containsAny 出现在任何未来的 String 变量中,那么将方法添加到类而不是对象:

    String.metaClass.containsAny={notAllowedTerms->
       notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
    }
    

    【讨论】:

      【解决方案8】:
      import org.apache.commons.lang.StringUtils;
      

      String Utils

      用途:

      StringUtils.indexOfAny(inputString, new String[]{item1, item2, item3})
      

      它将返回找到的字符串的索引,如果没有找到则返回-1。

      【讨论】:

      • JFI:我希望这个实现只在 inputString 上迭代一次,但我查看了 StringUtils 中的代码,遗憾的是它只是对默认 indexOf 进行 N 次调用。
      • 也许在 commons3 上实现更好!
      • 不,仍然只是迭代 org.apache.commons.lang3.StringUtils 中的字符串: for (int i = 0; i
      • 这不返回找到的字符串的索引(从数组中),只返回找到字符串的位置的索引。
      【解决方案9】:

      这是一种解决方案:

      public static boolean containsAny(String str, String[] words)
      {
         boolean bResult=false; // will be set, if any of the words are found
         //String[] words = {"word1", "word2", "word3", "word4", "word5"};
      
         List<String> list = Arrays.asList(words);
         for (String word: list ) {
             boolean bFound = str.contains(word);
             if (bFound) {bResult=bFound; break;}
         }
         return bResult;
      }
      

      【讨论】:

        【解决方案10】:

        如果你使用Java 8或以上版本,你可以依靠Stream API来做这样的事情:

        public static boolean containsItemFromArray(String inputString, String[] items) {
            // Convert the array of String items as a Stream
            // For each element of the Stream call inputString.contains(element)
            // If you have any match returns true, false otherwise
            return Arrays.stream(items).anyMatch(inputString::contains);
        }
        

        假设您有一大堆 String 来测试您也可以通过调用 parallel() 来并行启动搜索,那么代码将是:

        return Arrays.stream(items).parallel().anyMatch(inputString::contains); 
        

        【讨论】:

        • 我注意到一件奇怪的事情,我在字符串列表中有两个项目,我发现,当我使用“并行”时,它不会返回正确的结果。 (即使它包含值)。
        • @Charles.C 这很奇怪,我无法在我这边复制。
        • 我很确定在这里并行化流不是最理想的,除非输入字符串很长(~ 500 个字符)。相反,如果数组很大,最好对数组进行分区并并行运行每个数组。
        【解决方案11】:

        如果您正在寻找不区分大小写的匹配,请使用模式

        Pattern pattern = Pattern.compile("\\bitem1 |item2\\b",java.util.regex.Pattern.CASE_INSENSITIVE);
        
        Matcher matcher = pattern.matcher(input);
        if (matcher.find()) { 
            ...
        }
        

        【讨论】:

          【解决方案12】:

          自 Apache Common Lang 3 版本 3.4 起实现 containsAny 方法。

          【讨论】:

          • 检查 Char 数组
          【解决方案13】:

          如果您要搜索whole 单词,您可以这样做case insensitive

          private boolean containsKeyword(String line, String[] keywords)
          {
              String[] inputWords = line.split(" ");
          
              for (String inputWord : inputWords)
              {
                  for (String keyword : keywords)
                  {
                      if (inputWord.equalsIgnoreCase(keyword))
                      {
                          return true;
                      }
                  }
              }
          
              return false;
          }
          

          【讨论】:

            【解决方案14】:

            我们也可以这样做:

            if (string.matches("^.*?((?i)item1|item2|item3).*$"))
            
            (?i): used for case insensitive
            .*? & .*$: used for checking whether it is present anywhere in between the string.
            

            【讨论】:

            • 我相信用.* 包裹结尾会使?$ 变得多余,因为.* 表示“任何字符的零个或多个”(带有一些控制字符警告)跨度>
            【解决方案15】:

            在 Kotlin 中

            if (arrayOf("one", "two", "three").find { "onetw".contains(it) } != null){
                        doStuff()
                    }
            

            【讨论】:

            • 不确定是否适合使用与 9 年前要求的语言不同的语言添加格式错误的答案。
            猜你喜欢
            • 2018-11-20
            • 2020-11-03
            • 2019-03-13
            • 2015-09-08
            • 1970-01-01
            • 1970-01-01
            • 2020-12-01
            • 2017-11-21
            相关资源
            最近更新 更多