Verifica la matrice non vuota: nessuna?


191

È male verificare se un array non è vuoto usando il any?metodo?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

O è meglio usare unless a.empty??

Risposte:


248

any?non è lo stesso not empty?di alcuni casi.

>> [nil, 1].any?
=> true
>> [nil, nil].any?
=> false

Dalla documentazione:

Se il blocco non viene fornito, Ruby aggiunge un blocco implicito di {| obj | obj} (ovvero qualsiasi? restituirà vero se almeno uno dei membri della raccolta non è falso o nullo).


8
C'è qualche funzione opposta a empty??
RocketR,

12
@RocketR potresti voler provare il present?metodo.
Dantheta,

15
@dantastic #present?è solo Rails. In puro rubino otterrai NoMethodError: undefined method 'present?' for Array.
RocketR,

6
Non esattamente solo su rotaie, il supporto attivo può essere utilizzato senza rotaie, è sufficiente require 'activesupport'.
Sergio A.

83

La differenza tra un array che valuta i suoi valori trueo se è vuoto.

Il metodo empty?viene dalla classe Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Viene utilizzato per verificare se l'array contiene qualcosa o meno. Questo include cose che valutano false, come nile false.

>> a = []
=> []
>> a.empty?
=> true
>> a = [nil, false]
=> [nil, false]
>> a.empty?
=> false
>> a = [nil]
=> [nil]
>> a.empty?
=> false

Il metodo any?proviene dal modulo Enumerable.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

Viene utilizzato per valutare se "qualsiasi" valore nell'array viene valutato true. Metodi simili a questo sono none?, all?e one?, dove tutti basta controllare per vedere quante volte vero potrebbe essere valutata. che non ha nulla a che fare con il conteggio dei valori trovati in un array.

caso 1

>> a = []
=> []
>> a.any?
=> false
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> true

caso 2

>> a = [nil, true]
=> [nil, true]
>> a.any?
=> true
>> a.one?
=> true
>> a.all?
=> false
>> a.none?
=> false

caso 3

>> a = [true, true]
=> [true, true]
>> a.any?
=> true
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> false

31

Il prefisso dell'istruzione con un punto esclamativo consente di sapere se l'array non è vuoto. Quindi nel tuo caso -

a = [1,2,3]
!a.empty?
=> true

27
Doppia negazione? Sei serio?
3lvis,

29
Non è così serio!
Alexander Bird,

5
Hehe. La doppia negazione non è l'ideale, sembra solo più leggibile in questo caso specifico.
Denny Abraham Cheriyan,

12
Il doppio negativo faceva parte della domanda originale "Controlla array non vuoto". Questo risponde alla domanda.
mattfitzgerald,

30

Evitare any?per array di grandi dimensioni.

  • any? è O(n)
  • empty? è O(1)

any? non controlla la lunghezza ma esegue la scansione dell'intero array alla ricerca di elementi veritieri.

static VALUE
rb_ary_any_p(VALUE ary)
{
  long i, len = RARRAY_LEN(ary);
  const VALUE *ptr = RARRAY_CONST_PTR(ary);

  if (!len) return Qfalse;
  if (!rb_block_given_p()) {
    for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
  }
  else {
    for (i = 0; i < RARRAY_LEN(ary); ++i) {
        if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
    }
  }
  return Qfalse;
}

empty? d'altra parte controlla solo la lunghezza dell'array.

static VALUE
rb_ary_empty_p(VALUE ary)
{
  if (RARRAY_LEN(ary) == 0)
    return Qtrue;
  return Qfalse;
}

La differenza è rilevante se si hanno array "sparsi" che iniziano con molti nilvalori, come ad esempio un array appena creato.


In questo caso utilizzare la differenza è rilevante solo se si dispone di array "sparsi" che iniziano con un sacco di nilvalori, con gli array "normali" any?, senza dichiarazioni di blocco al primo elemento, quindi la complessità è ancora O (1) come il empty?metodo di
David Costa

4

Suggerirò di usare unlesse blankper verificare che sia vuoto o meno.

Esempio :

unless a.blank?
  a = "Is not empty"
end

Questo saprà "a" vuoto o no. Se 'a' è vuoto, il codice seguente non verrà eseguito.


4
#blank?fa parte di Rails. Se stanno già usando Rails, #present?è #blank?comunque la negazione .
Eva,

0

Non credo sia affatto male da usare any?. Lo uso molto. È chiaro e conciso.

Tuttavia, se sei preoccupato per tutti i nilvalori che lo scaricano, allora stai davvero chiedendo se l'array ha size > 0. In tal caso, questa semplice estensione morta (NON ottimizzata, in stile scimmia) ti avvicinerebbe.

Object.class_eval do

  def size?
    respond_to?(:size) && size > 0
  end

end

> "foo".size?
 => true
> "".size?
 => false
> " ".size?
 => true
> [].size?
 => false
> [11,22].size?
 => true
> [nil].size?
 => true

Questo è abbastanza descrittivo, logicamente chiedendo "questo oggetto ha una dimensione?". Ed è conciso e non richiede ActiveSupport. Ed è facile da costruire.

Alcuni extra a cui pensare:

  1. Questo non è lo stesso present?di ActiveSupport.
  2. Potresti volere una versione personalizzata per String, che ignora gli spazi bianchi (come present?fa).
  3. Si potrebbe desiderare il nome length?per Stringo di altro tipo in cui potrebbe essere più descrittivo.
  4. Potresti volerlo personalizzato per Integere altri Numerictipi, in modo che ritorni uno zero logico false.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.