ChatGPT解决这个技术问题 Extra ChatGPT

Test if a string contains any of the strings from an array

How do I test a string to see if it contains any of the strings from an array?

Instead of using

if (string.contains(item1) || string.contains(item2) || string.contains(item3))
Are you asking if a string is equal to any of the strings in the array, or contains any of the strings from in the array?
You want to check if any string from the array is a substring of your input string? Or you want to check if your input string equals one of the string in the array? Can you be more precise?
contains, so that it takes a line and sees if it contains any of the words from a list (stored as an array of strings)

g
gnomed

EDIT: Here is an update using the Java 8 Streaming API. So much cleaner. Can still be combined with regular expressions too.

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

Also, if we change the input type to a List instead of an array we can use items.stream().anyMatch(inputStr::contains).

You can also use .filter(inputStr::contains).findAny() if you wish to return the matching string.

Important: the above code can be done using parallelStream() but most of the time this will actually hinder performance. See this question for more details on parallel streaming.

Original slightly dated answer:

Here is a (VERY BASIC) static method. Note that it is case sensitive on the comparison strings. A primitive way to make it case insensitive would be to call toLowerCase() or toUpperCase() on both the input and test strings.

If you need to do anything more complicated than this, I would recommend looking at the Pattern and Matcher classes and learning how to do some regular expressions. Once you understand those, you can use those classes or the String.matches() helper method.

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

How to use it with regular expression @gnomed
How can we make the first implementation case sensitive ?
The implementations are case sensitive already. I also have instructions for how to make it case insensitive in the bottom paragraphs of the answer.
parallelStream uses a minimum batch size of 1024, it won't actually parallelise small lists. It's a footgun.
@CallumRogers true, I kind of left it in just so people think about it, but agree the vast majority of the time it will not make much difference (or actually be a detriment) compared to a non-parallel stream. Will try to call that out more in the answer.
f
ford prefect
import org.apache.commons.lang.StringUtils;

String Utils

Use:

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

It will return the index of the string found or -1 if none is found.


JFI: I hoped this implementation to iterate only once over the inputString, but I looked at the code in StringUtils, and sadly it's just doing N calls of the default indexOf.
Maybe on commons3 the implementation is better!
Nope, still just iterates over the Strings in org.apache.commons.lang3.StringUtils: for (int i = 0; i < searchStrs.length; i++) { CharSequenceUtils.indexOf(str, search, 0); ....
This does not return the index of the string found (from the array), only the index of the position the string was found at.
a
anubhava

You can use String#matches method like this:

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

N
Nicolas Filotto

If you use Java 8 or above, you can rely on the Stream API to do such thing:

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

Assuming that you have a big array of big String to test you could also launch the search in parallel by calling parallel(), the code would then be:

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

One strange thing I noticed, I have two item in the String list, I found out, when i use 'parallel' it will not return the correct results. (even if it contains the value).
@Charles.C that's weird I can't reproduce on my side.
I am pretty sure parallelizing the stream would be suboptimal here unless input string was long (~ 500 chars). Instead if the array was large, It would probably be better to partitition the array and run each of those in parallel.
J
JAN

The easiest way would probably be to convert the array into a java.util.ArrayList. Once it is in an arraylist, you can easily leverage the contains method.

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

This is incorrect. OP is asking if string contains any Strings in the array, not if any Strings in the array contain string.
@BeauGrantham I was thinking this too, but the OP is using .equals() in their post, which is very confusing. I reckon they need to edit their question
@BeauGrantham Man I couldn't sworn I understood the problem. Maybe the question needs to be clarified a bit more?
No, this kind of inverse direction won't work, you should check if String contains ONE of the values given and NOT if the values gives contain the string.
Question is the opposite
s
serup

Here is one solution :

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

A
Arthur Vaïsse

Since version 3.4 Apache Common Lang 3 implement the containsAny method.


That checks for Char array
Ó
Óscar López

Try this:

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

Question is the opposite: Does the target string contain any of the list’s strings.
stream() and anyMatch() requires API level 24 or above
@DilankaLaksiri not really, those methods have been available since Java 8. And the latest version of Java is 16, so what "API level 24" are you referring to?
@ÓscarLópez I'm talking about the Android API level.
Ok, good. But this question was not about Android :)
I
Ivan Arrizabalaga

A more groovyesque approach would be to use inject in combination with metaClass:

I would to love to say:

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

And the method would be:

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

If you need containsAny to be present for any future String variable then add the method to the class instead of the object:

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

C
Chandan Kolambe

We can also do like this:

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

I believe wrapping the ends with .* makes the ? and $ redundant, as .* means "zero or more of any characters" (with some control char caveats)
t
thanos.a

If you are seraching for whole words you can do this that works 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;
}

f
fdermishin

And if you are looking for case insensitive match, use pattern

Pattern pattern = Pattern.compile("\\bitem1 |item2\\b",java.util.regex.Pattern.CASE_INSENSITIVE);

Matcher matcher = pattern.matcher(input);
if (matcher.find()) { 
    ...
}

H
H.Step

in Kotlin

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

Not sure if adding a badly formatted answer in a different language than what had been asked for 9 years ago is appropriate.
P
Prahalad Deshpande

The below should work for you assuming Strings is the array that you are searching within:

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

where mykeytosearch is the string that you want to test for existence within the array. mysearchComparator - is a comparator that would be used to compare strings.

Refer to Arrays.binarySearch for more information.


It should be noted that binarySearch works only on array that are sorted, either naturally or by the given comparator (if such is given).
G
Garrett Hall
if (Arrays.asList(array).contains(string))

Question is the opposite: Does the target string contain any of the list’s strings.