2012-01-24 16 views
84

Jak przetestować ciąg znaków, aby sprawdzić, czy zawiera on ciągi z tablicy?Sprawdź, czy łańcuch zawiera którykolwiek z łańcuchów z tablicy

Zamiast

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

Pytasz czy ciąg jest równy ** ** jednego z ciągów w tablicy, lub ** zawiera ** dowolny ciąg z tablicy? – Natix

+1

Chcesz sprawdzić, czy dowolny ciąg znaków z tablicy jest podciąganym ciągiem wejściowym? Lub chcesz sprawdzić, czy Twój ciąg wejściowy * jest równy * jednemu z ciągów w tablicy? Czy możesz być bardziej precyzyjny? –

+1

zawiera tak, że pobiera wiersz i widzi, czy zawiera jakiekolwiek słowo z listy (przechowywane jako tablica łańcuchów). – user1060828

Odpowiedz

93

EDYCJA: Tutaj jest aktualizacja przy użyciu API Java 8 Streaming. O wiele czystszy. Można nadal łączyć z wyrażeniami regularnymi.

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

Ponadto, jeśli zamiast tego zmienić typ wejścia do listy tablicy możemy użyć items.parallelStream().anyMatch(inputStr::contains).

Możesz również użyć .filter(inputStr::contains).findAny(), jeśli chcesz zwrócić pasujący ciąg.


Original nieco przestarzały odpowiedź:

Oto (bardzo podstawowy) metoda statyczna. Zwróć uwagę, że w łańcuchach porównania rozróżniana jest wielkość liter. Aby uczynić go niewrażliwym na wielkość liter, należy wywołać toLowerCase() lub toUpperCase() zarówno na łańcuchach wejściowych, jak i testowych.

Jeśli chcesz zrobić coś bardziej skomplikowanego, polecam przejrzeć klasy Pattern i Matcher i nauczyć się wykonywać niektóre wyrażenia regularne. Po ich zrozumieniu można użyć tych klas lub metody pomocniczej 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; 
} 
17

Najprostszym sposobem byłoby prawdopodobnie przekształcić tablicę do java.util.ArrayList. Gdy znajduje się na liście tablic, możesz łatwo wykorzystać metodę zawiera.

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

To jest niepoprawne. OP pyta, czy 'string' zawiera jakiekolwiek' String's w tablicy, a nie jeśli 'String's w tablicy zawiera' string'. –

+3

@ Beautograntham Myślałem o tym również, ale OP używa ".equals()" w swoim poście, co jest bardzo mylące. Sądzę, że muszą edytować swoje pytanie. – gnomed

+0

@ BeauGrantham Człowiek, którego nie mogłem przysiąc, że zrozumiałem problem. Może pytanie wymaga nieco więcej wyjaśnienia? –

7

Spróbuj tego:

if (Arrays.asList(item1, item2, item3).contains(string)) 
+9

Pytanie jest odwrotne: Czy ciąg docelowy zawiera którykolwiek z ciągów listy. –

+0

Pytanie jest przeciwieństwem – sgrillon

1
if (Arrays.asList(array).contains(string)) 
+8

Pytanie jest odwrotne: Czy docelowy ciąg zawiera którykolwiek z ciągów listy. –

+2

Pytanie jest odwrotne – sgrillon

27

Można użyć String#matches metody takie jak to:

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

Poniższa powinny pracować dla Ciebie zakładając Strings jest tablica, że przeszukują w:

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

gdzie mykeytosearch jest ciągiem, który chcesz przetestować pod kątem istnienia w tablicy. mysearchComparator - to komparator, który byłby używany do porównywania ciągów.

Aby uzyskać więcej informacji, patrz Arrays.binarySearch.

+2

Należy zauważyć, że binarySearch działa tylko na tablicy, która jest posortowana, naturalnie lub przez dany komparator (jeśli taki jest podany). – Natix

0

Bardziej groovyesque podejście byłoby użyć wstrzyknąć w połączeniu z metaklasa:

Chciałbym kochać powiedzieć:

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

A metoda będzie:

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

Jeśli potrzebujesz containsAny być obecny na każdej przyszłej zmienna String następnie dodać metodę do klasy zamiast obiektu:

String.metaClass.containsAny={notAllowedTerms-> 
    notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)}) 
} 
40
import org.apache.commons.lang.StringUtils; 

String Utils

Zastosowanie:

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

Zwróci indeks znalezionego ciągu lub -1, jeśli nie zostanie znaleziony.

+4

JFI: Miałem nadzieję, że ta implementacja będzie iterować tylko raz nad inputString, ale przyjrzałem się kodowi w StringUtils, a niestety po prostu wykonuję N wywołań domyślnego indexOf. – alfonx

+0

Może na commons3 wdrożenie jest lepsze! – renanlf

+0

Nie, nadal tylko iteruje po ciągach w org.apache.commons.lang3.StringUtils: dla (int i = 0; i alfonx

2

Oto jedno rozwiązanie:

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
String.prototype.matchWithTokens = function(tokensArray){ 
    for(i=0; i< tokensArray.length; i++) { 
    if(this.indexOf(tokensArray[i]) != -1) { 
     return true; 
    } 
    } 
    return false; 
}; 
+0

To nie jest nawet kod Java. – Hamdi

7

Jeśli używasz Java 8 lub powyżej, można polegać na Stream API zrobić coś takiego:

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

Zakładając, że masz duży zestaw String do przetestowania, możesz również zrównoleglić wyszukiwanie przez wywołanie parallel(), kod będzie wtedy:

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

Jedna dziwna rzecz, którą zauważyłem, mam dwie pozycje na liście ciągów, dowiedziałem się, że kiedy używam "równoległości", to nie zwróci poprawnych wyników. (nawet jeśli zawiera wartość). –

+0

@ Charles.C to dziwne, że nie mogę powtórzyć po mojej stronie. –

0

A jeśli szukasz przypadku meczu niewrażliwego, wykorzystanie wzorca

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

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

} 
Powiązane problemy