Bir dizenin bir dizideki dizelerden herhangi birini içerip içermediğini test edin


153

Bir dizeden dizeden herhangi birini içerip içermediğini görmek için bir dizeyi nasıl test edebilirim?

Kullanmak yerine

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

4
Bir dizenin dizideki dizelerden herhangi birine eşit olup olmadığını mı yoksa dizideki dizelerden herhangi birini içerip içermediğini mi soruyorsunuz ?
Natix

1
Dizideki herhangi bir dizenin giriş dizenizin bir alt dizesi olup olmadığını kontrol etmek ister misiniz? Veya giriş dizenizin dizideki dizeden birine eşit olup olmadığını kontrol etmek mi istiyorsunuz ? Daha kesin olabilir misin?
Savino Sguera

1
içerir, böylece bir satır alır ve bir listedeki kelimelerden herhangi birini içerip içermediğini görür (dizeler dizisi olarak depolanır)
arowell

Yanıtlar:


188

EDIT: İşte Java 8 Streaming API kullanarak bir güncelleme. Çok daha temiz. Yine de düzenli ifadelerle birleştirilebilir.

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

Ayrıca, girdi türünü bir dizi yerine bir Liste olarak değiştirirsek, items.parallelStream().anyMatch(inputStr::contains) .

.filter(inputStr::contains).findAny()Eşleşen dizeyi döndürmek istiyorsanız da kullanabilirsiniz .


Orijinal biraz tarihli cevap:

İşte bir (ÇOK TEMEL) statik yöntem. Karşılaştırma dizelerinde büyük / küçük harfe duyarlı olduğunu unutmayın. Büyük / küçük harfe duyarsız hale getirmenin ilkel bir yolu , hem giriş hem de test dizelerini çağırmak toLowerCase()ya da çağırmak olacaktır toUpperCase().

Bundan daha karmaşık bir şey yapmanız gerekiyorsa, Pattern ve Matcher sınıflarına bakmanızı ve bazı düzenli ifadelerin nasıl yapılacağını öğrenmenizi öneririm . Bunları anladıktan sonra, bu sınıfları veya String.matches()yardımcı yöntemi kullanabilirsiniz.

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

1
Düzenli ifade ile nasıl kullanılır @gnomed
Praneeth

İlk uygulama durumunu nasıl hassas hale getirebiliriz?
thanos.a

Uygulamalar zaten büyük / küçük harfe duyarlıdır. Ayrıca cevabın alt paragraflarında davanın nasıl duyarsız hale getirileceğine dair talimatlar var.
21'de gnomed

52
import org.apache.commons.lang.StringUtils;

String Utils

kullanın:

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

Bulunan dizenin dizinini veya hiçbiri bulunmazsa -1 değerini döndürür.


7
JFI: Bu uygulamayı inputString üzerinden yalnızca bir kez yinelemek için umut, ancak StringUtils koduna baktım ve ne yazık ki sadece varsayılan indexOf N çağrıları yapıyor.
alfonx

Belki commons3 üzerinde uygulama daha iyidir!
renanleandrof

1
Hayır, yine de org.apache.commons.lang3.StringUtils içindeki Dizeleri yineliyor: for (int i = 0; i <searchStrs.length; i ++) {CharSequenceUtils.indexOf (str, search, 0); ....
alfonx

Bu, bulunan dizenin dizinini (diziden) döndürmez, yalnızca dizenin bulunduğu konumun dizinini döndürür.
Pluto

33

String # match yöntemini şu şekilde kullanabilirsiniz :

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

16

En kolay yol muhtemelen diziyi bir java.util.ArrayList'e dönüştürmektir. Bir arrayliste girdikten sonra, içerme yöntemini kolayca kullanabilirsiniz.

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

70
Bu yanlış. Eğer OP istiyor stringherhangi birini içeren Stringdizideki s, herhangi bir değilse Stringdizinin s içerir string.
Beau Grantham

3
@BeauGrantham Ben de bunu düşünüyordum, ama OP yazılarında .equals()çok kafa karıştırıcı. Onların sorularını düzenlemeleri gerektiğini
sanıyorum

@BeauGrantham Adam yemin edemedim sorunu anladım. Belki de sorunun biraz daha açıklığa kavuşturulması gerekiyor?
Roy Kachouh

1
Hayır.
Vladimir Stazhilov

2
Soru tam tersi
Stéphane GRILLON

16

Eğer kullanırsanız Java 8 veya üstünde, güvenebileceğiniz Akış API böyle bir şey yapmak için:

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

StringTest etmek için büyük bir dizi diziniz olduğu varsayılarak aramayı paralel olarak başlatabileceğinizi varsayarsak parallel(), kod şöyle olur:

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

Fark ettiğim garip bir şey, Dize listesinde iki öğe var, öğrendim, 'paralel' kullandığımda doğru sonuçları döndürmeyecek. (değeri içeriyor olsa bile).
CharlesC

@ Charles.C benim tarafımda üreyemediğim garip.
Nicolas Filotto

Giriş dizesi uzun (~ 500 karakter) sürece akış paralelleme burada en iyi olurdu eminim. Bunun yerine dizi büyük olsaydı, diziyi bölümlere ayırmak ve her birini paralel olarak çalıştırmak daha iyi olurdu.
yaşam boyu olağanüstü

2

İşte bir çözüm:

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


1

Daha mükemmel bir yaklaşım, enjeksiyonu metaClass ile birlikte kullanmak olacaktır :

Söylemek isterim:

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

Ve yöntem şöyle olurdu:

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

Eğer gerekiyorsa containsAny ileride dize değişkeni sonra yerine nesnenin sınıfına yöntemi ekleyin hazır bulunmak için:

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


0

Ve büyük / küçük harfe duyarlı olmayan eşleşme arıyorsanız, desen kullanın

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

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

}

0

Tam kelimeler için seraching ediyorsanız, bunu büyük / küçük harfe duyarsız çalıştırabilirsiniz .

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

0

Bunu da yapabiliriz:

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

-3

Aşağıda, Dizelerin içinde aradığınız dizi olduğunu varsayarak çalışmanız gerekir :

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

burada mykeytosearch, dizideki varlığını test etmek istediğiniz dizedir. mysearchComparator - dizeleri karşılaştırmak için kullanılacak bir karşılaştırıcıdır.

Arrays.binarySearch sayfasına bakın fazla bilgi .


2
BinarySearch'ün sadece doğal olarak veya verilen karşılaştırıcı tarafından (eğer verildiyse) sıralanan dizi üzerinde çalıştığı unutulmamalıdır.
Natix

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.