È questo comportamento previsto per String.containsOnly ()?

Sep 11 2020

Ecco del codice per illustrare il problema.

String str1 = '';
System.debug(str1.containsOnly('W'));

Mi sarei aspettato falsecome risultato ma sorprendentemente il risultato è stato true. Non capisco perché questo sia il caso considerando che una stringa vuota non contiene un 'W'carattere. È questo comportamento previsto o un bug?

Modifica : dopo le risposte che ho ricevuto finora, penso di dover riformulare la mia domanda e renderla più fondamentale. In questo modo, verrà data risposta alla domanda originale.

Un presupposto di fondo che sto facendo è che la documentazione del metodo ha preceduto ed è stata la base dell'implementazione del metodo e non viceversa. Se ritieni che questa ipotesi sia sbagliata, fammelo sapere.

Tralasciando così come containsOnly()è attualmente implementato, come va intesa la documentazione del metodo? È più una questione di significato o semantica che tecnica. Questa è la descrizione fornita.

contieneOnly (inputString) Restituisce true se la stringa corrente contiene solo caratteri della sequenza di caratteri specificata e non altri caratteri; in caso contrario, restituisce false.

Ecco le possibili interpretazioni fino ad ora:

  1. La stringa corrente non contiene caratteri al di fuori dei caratteri nella stringa di input. (@PhilW)

  2. La stringa corrente contiene uno qualsiasi dei caratteri nella stringa di input ( containsAny(inputString)) && interpretazione 1. (La mia comprensione).

Per favore fatemi sapere come avete capito la documentazione o la frase contiene solo e se avete altre interpretazioni plausibili, le aggiungerò all'elenco. Penso che sia necessario un consenso su questo prima di entrare nell'attuazione effettiva del metodo.

Risposte

8 PhilW Sep 11 2020 at 13:10

Logicamente, sì, perché la stringa vuota non contiene caratteri non consentiti.

I caratteri non consentiti sono caratteri non esplicitamente elencati nella specifica "solo". Quindi in questo caso è qualsiasi lettera diversa dalla "W".

Se stessi implementando questo metodo da solo, farei qualcosa del tipo:

public Boolean containsOnly(String allowed) {
    // "chars" is the internal array of characters in the string
    for (Integer i = 0; i < chars.size(); i++) {
        if (allowed.indexOfChar(chars[i]) < 0) {
            return false;
        }
    }

    return true;
}

Il punto è che è un'iterazione compatta alla ricerca di caratteri non consentiti con uscita anticipata come richiesto e se non trovi caratteri non consentiti restituisci semplicemente vero.

Non credo che questo comportamento possa essere considerato un bug; è un risultato naturale del controllo in modo compatto ed efficiente. Puoi anche visualizzare una stringa vuota come zero istanze del carattere "W". String.containsOnlyrestituirà true per:

  • zero caratteri 'W' (la stringa vuota)
  • un carattere "W" (la stringa "W")
  • due caratteri "W" (la stringa "WW")
  • eccetera.

Se vuoi verificare di avere una stringa non vuota e contiene solo i caratteri specificati, adatta il tuo codice per fare:

if (str1.isNotEmpty() && str1.containsOnly('W')) {
   ...
}
3 nbrown Sep 11 2020 at 21:43

Sono propenso a pensare che questo non sia un bug ed è un comportamento standard, ma la documentazione è al massimo ambigua e non fornisce indicazioni su come dovrebbe funzionare una stringa vuota . Ulteriori chiarimenti sono giustificati dato che containse containsOnlyrestituiscono risultati diversi in questi scenari:

''.contains('W');     //false
''.containsOnly('W'); //true

Addendum : alcuni esempi aggiuntivi che mostrano come questa funzione sia più simile a un set rispetto a quella containsche cerca una sottostringa in una determinata stringa:

'abab'.containsOnly('ab');   //true
'ab'.containsOnly('abab');   //true
'abab'.containsOnly('abcd'); //true

'abab'.contains('ab');       //true
'ab'.contains('abab');       //false
'abab'.contains('abc');      //false

L' containsOnlyoperazione dovrebbe essere definita in termini matematici e ho la sensazione che sia implementata in questo modo. Non esiste esattamente un'operazione come containsOnly( che io sappia - non sono un matematico ), ma puoi arrivarci in due modi con le operazioni sugli insiemi standard. Se prendi l'intersezione (∩) dei due insiemi e l'intersezione è la stessa del tuo primo operando true, significa che i due insiemi si sovrappongono completamente:

{A, B} ∩ {A, B} = {A, B}

{} ∩ {A, B} = {}

Ma le regole dell'algebra degli insiemi trattano un insieme vuoto in un modo unico in quanto tutte le seguenti sono equivalenti:

{} ∩ {A, B} ≡ {} ∩ {} ≡ {}

Questo spiegherebbe perché una stringa vuota, che è un "insieme" di caratteri vuoto, restituirebbe sempre true quando l'operazione viene eseguita su di essa. L'intersezione dell'insieme vuoto con qualsiasi altro insieme (incluso un altro insieme vuoto) è sempre l'insieme vuoto.

Questo era un modo per implementare una containsOnlyfunzione utilizzando le operazioni sugli insiemi. L'altro è usare la differenza (\). Se la differenza di due serie è la stessa dell'originale, potresti dire che la prima serie contiene solo la seconda. Anche in questo caso, l'insieme vuoto si comporta in modo simile all'utilizzo di un'intersezione.

{A, B} \ {A} = {B}

{A, B} \ {A, B} = {} ≡ {} \ {A, B} = {} ≡ {} \ {} = {}

La mia ipotesi è che containsOnlyvenga implementato utilizzando uno di questi metodi per il suo algoritmo e la documentazione per la Stringclasse deve essere aggiornata per riflettere la metodologia corrente del metodo (in modo che i futuri sviluppatori siano consapevoli delle sfumature). Oppure il metodo dovrebbe essere cambiato per essere reso coerente contains.