2012-04-18 32 views
43

Ho una variabile stringa, str con valori possibili, val1, val2 e val3.Confrontare una stringa con più valori in un'unica espressione

voglio mettere a confronto (a parità di caso) str a tutti questi valori utilizzando un'istruzione if, per esempio:

if("val1".equalsIgnoreCase(str)||"val2".equalsIgnoreCase(str)||"val3.equalsIgnoreCase(str)) 
{ 
     //remaining code 
} 

C'è un modo per evitare di usare più OR (||) operatori e confrontare valori in una espressione? Ad esempio, in questo modo:

if(("val1" OR "val2" OR "val3").equalsIgnoreCase(str) //this is only an idea. 
+0

possibile duplicato [Una dichiarazione IF Cleaner] (http://stackoverflow.com/questions/20952325/a-cleaner-if-statement) – WoodenKitty

risposta

73

Ho trovato una soluzione migliore. Ciò può essere ottenuto utilizzando RegEx:

if (str.matches("val1|val2|val3")) { 
    // remaining code 
} 

Per il caso di corrispondenza insensitive:

if (str.matches("(?i)val1|val2|val3")) { 
    // remaining code 
} 
+0

La funzione 'matches' non funziona bene per tutti i casi. La risposta di @hmjd lo ha fatto per il mio caso. Vedi [Regex non funziona in String.matches()] (http://stackoverflow.com/questions/8923398/regex-doesnt-work-in-string-matches) per maggiori informazioni. – Primoz990

10

è possibile memorizzare tutte le stringhe che si desidera confrontare con str in una collezione e verificare se la raccolta contiene str. Memorizzare tutte le stringhe nella raccolta in minuscolo e convertire str in caratteri minuscoli prima di eseguire una query sulla raccolta. Ad esempio:

Set<String> strings = new HashSet<String>(); 
strings.add("val1"); 
strings.add("val2"); 

String str = "Val1"; 

if (strings.contains(str.toLowerCase())) 
{ 
} 
+0

Cosa succede se str contiene valore come "val" solo ??? –

+0

È possibile popolare la raccolta con qualsiasi valore richiesto. Nel caso in cui 'str' fosse' "val" 'allora nel codice nella mia risposta' strings.contains() 'restituire' false'. – hmjd

+0

No no sto dicendo che se qualcuno passa il valore str come "Val" che non è uguale a "Val1", "Val2", "Val3". Ciò significa che il valore di passaggio str come "Val" deve essere fallito .. ma in il tuo caso sarà superato.Non soddisfa le mie condizioni –

-2

No, non esiste tale possibilità. Allthough, poteva immaginare:

public static boolean contains(String s, Collection<String>c) { 
    for (String ss : c) { 
     if (s.equalsIgnoreCase(ss)) return true; 
    } 
    return false; 
} 
+0

le raccolte che vale la pena considerare, come HashSet, contains() ha un'implementazione molto più efficiente: –

+0

Vero, ma (che potrebbe essere un punto controverso), equals and equalsIgnoreCase non producono lo stesso risultato, che potrebbe naturalmente essere superato memorizzando le stringhe come minuscolo e minuscolo la chiave che stai cercando, ma, YMMV – slipset

2

Basta usare var-args e scrivere il proprio metodo statico:

public static boolean compareWithMany(String first, String next, String ... rest) 
{ 
    if(first.equalsIgnoreCase(next)) 
     return true; 
    for(int i = 0; i < rest.length; i++) 
    { 
     if(first.equalsIgnoreCase(rest[i])) 
      return true; 
    } 
    return false; 
} 

public static void main(String[] args) 
{ 
    final String str = "val1"; 
    System.out.println(compareWithMany(str, "val1", "val2", "val3")); 
} 
+0

Mi piace questo! Probabilmente sto trascurando qualcosa, ma perché includi 'next' come parametro? Questo può anche essere parte del riposo di var-args, giusto? – Martijn

+0

Avendo 'next' imposto il passaggio di almeno _one_ parametro. Quindi non puoi fare 'compareWithMany (" pippo ")'. È un controllo di integrità in fase di compilazione, invece di dover gestire un set vuoto da confrontare durante il runtime. – Neet

0

È possibile raggiungere questo obiettivo con quadro collezioni. Metti tutte le tue opzioni in una raccolta dire qualcosa come Collection<String> options;

Quindi ripetere questo ciclo per confrontare la stringa con gli elementi dell'elenco e se è possibile è possibile restituire un valore booleano vero e altrimenti falso.

2

ArrayUtils può essere utile.

ArrayUtils.contains(new String[]{"1", "2"}, "1") 
3

Piccolo miglioramento per perfettamente valida @hmjd's answer: è possibile utilizzare seguente sintassi: si

class A { 

    final Set<String> strings = new HashSet<>() {{ 
    add("val1"); 
    add("val2"); 
    }}; 

    // ... 

    if (strings.contains(str.toLowerCase())) { 
    } 

    // ... 
} 

Permette di inizializzare si Set sul posto.

-3
!string.matches("a|b|c|d") 

funziona bene per me.

+6

Si prega di fornire spiegazione/motivo per una risposta migliore, è troppo breve –

+1

Come è diverso dalla risposta accettata? –

17

In Java 8 +, è possibile utilizzare un Stream<T> e anyMatch(Predicate<? super T>) con qualcosa come

if (Stream.of("val1", "val2", "val3").anyMatch(str::equalsIgnoreCase)) { 
    // ... 
} 
+3

Questa dovrebbe essere la risposta accettata! – higuaro

0

Ricorda in Java una stringa tra virgolette è ancora un oggetto String.Pertanto è possibile utilizzare la funzione di stringa contiene() per testare una serie di stringhe o interi con questo metodo:

if ("A C Viking G M Ocelot".contains(mAnswer)) {...} 

per i numeri è un po 'più coinvolto, ma funziona ancora:

if ("1 4 5 9 10 17 23 96457".contains(String.valueOf(mNumAnswer))) {...} 
Problemi correlati