Compruebe si la matriz no está vacía: ¿alguna?

191

¿Es malo verificar si una matriz no está vacía mediante el any?método?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

¿O es mejor usar unless a.empty??

sivabudh
fuente

Respuestas:

248

any?No es lo mismo que not empty?en algunos casos.

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

De la documentación:

Si no se proporciona el bloque, Ruby agrega un bloque implícito de {| obj | obj} (¿es cualquier? devolverá verdadero si al menos uno de los miembros de la colección no es falso o nulo).

Marcel Jackwerth
fuente
8
¿Hay alguna función opuesta a empty??
RocketR
12
@RocketR es posible que desee comprobar el present?método de pago .
dantheta
15
@dantastic #present?es solo para Rails. En puro Ruby obtendrás NoMethodError: undefined method 'present?' for Array.
RocketR
66
No es exactamente solo Rails, Active Support se puede usar sin rails, solo es necesario require 'activesupport'.
Sergio A.
83

La diferencia entre una matriz que evalúa sus valores trueo si está vacía.

El método empty?proviene de la clase Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Se utiliza para verificar si la matriz contiene algo o no. Esto incluye cosas que evalúan a false, como nily false.

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

El método any?proviene del módulo Enumerable.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

Se utiliza para evaluar si "cualquier" valor en la matriz se evalúa true. Métodos similares a esto son none?, all?y one?, donde todos solo verifican para ver cuántas veces podría evaluarse la verdad. que no tiene nada que ver con el recuento de valores encontrados en una matriz.

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
Empujador poligonal
fuente
31

Prefijar la declaración con un signo de exclamación le permitirá saber si la matriz no está vacía. Entonces en tu caso ...

a = [1,2,3]
!a.empty?
=> true
Denny Abraham Cheriyan
fuente
27
¿Doble negación? ¿En serio?
3lvis
29
Él no es tan serio!
Alexander Bird
55
Jeje. La doble negación no es ideal, solo parece más legible en este caso específico.
Denny Abraham Cheriyan
12
El doble negativo era parte de la pregunta original "Verificar que la matriz no esté vacía". Esto responde a la pregunta.
mattfitzgerald
30

Evitar any?para grandes matrices.

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

any? no comprueba la longitud, pero en realidad escanea toda la matriz en busca de elementos verdaderos.

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? por otro lado, solo verifica la longitud de la matriz.

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

La diferencia es relevante si tiene matrices "dispersas" que comienzan con muchos nilvalores, como por ejemplo una matriz que acaba de crearse.

akuhn
fuente
En este caso de uso, la diferencia es relevante solo si tiene matrices "dispersas" que comienzan con muchos nilvalores, con matrices "normales" any?sin retornos de bloque en el primer elemento, por lo que la complejidad sigue siendo O (1) como el empty?método
David Costa
4

Sugeriré usar unlessy blankpara comprobar si está vacío o no.

Ejemplo:

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

Esto sabrá 'a' vacío o no. Si 'a' está en blanco, el siguiente código no se ejecutará.

Dennis
fuente
44
#blank?Es parte de Rails. Si ya están usando Rails, #present?es la negación de #blank?todos modos.
Eva
0

No creo que sea malo usarlo any?en absoluto. Lo uso mucho. Es claro y conciso.

Sin embargo, si le preocupa que todos los nilvalores lo descarten, entonces realmente está preguntando si la matriz lo ha hecho size > 0. En ese caso, esta extensión simple (NO optimizada, estilo mono) te acercaría.

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

Esto es bastante descriptivo, lógicamente preguntando "¿este objeto tiene un tamaño?". Y es conciso, y no requiere ActiveSupport. Y es fácil de construir.

Algunos extras para pensar:

  1. Esto no es lo mismo que present?de ActiveSupport.
  2. Es posible que desee una versión personalizada para String, que ignora los espacios en blanco (como lo present?hace).
  3. Quizás quieras el nombre length? de Stringu otros tipos donde podría ser más descriptivo.
  4. Es posible que desee personalizarlo Integery otros Numerictipos, de modo que se devuelva un cero lógico false.
lilole
fuente