Überprüfen Sie, ob das Array nicht leer ist.

189

Ist es schlecht, mit der Methode zu überprüfen, ob ein Array nicht leer ist any??

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

Oder ist es besser zu benutzen unless a.empty??

Sivabudh
quelle

Antworten:

246

any?ist nicht das gleiche wie not empty?in einigen Fällen.

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

Aus der Dokumentation:

Wenn der Block nicht angegeben ist, fügt Ruby einen impliziten Block von {| obj | hinzu obj} (das ist einer? gibt true zurück, wenn mindestens eines der Sammlungsmitglieder nicht false oder nil ist).

Marcel Jackwerth
quelle
8
Gibt es eine Funktion gegenüber empty??
RocketR
12
@RocketR Vielleicht möchten Sie die Checkout- present?Methode.
Dantheta
15
@dantastic #present?ist nur für Rails. In reinem Ruby bekommst du NoMethodError: undefined method 'present?' for Array.
RocketR
6
Active Support ist nicht nur für Rails gedacht, sondern kann auch ohne Rails verwendet werden require 'activesupport'.
Sergio A.
82

Der Unterschied zwischen einem Array, das seine Werte bewertet trueoder leer ist.

Die Methode empty?stammt aus der Array-Klasse
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Es wird verwendet, um zu überprüfen, ob das Array etwas enthält oder nicht. Dies schließt Dinge ein, die bewertet werden false, wie z. B. nilund false.

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

Die Methode any?stammt aus dem Enumerable-Modul.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

Es wird verwendet, um zu bewerten, ob "irgendein" Wert im Array ausgewertet wird true. Ähnliche Methoden dazu sind none?, all?und one?, wo sie alle nur zu sehen , prüfen, wie oft wahr ausgewertet werden kann. Das hat nichts mit der Anzahl der in einem Array gefundenen Werte zu tun.

Fall 1

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

Fall 2

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

Fall 3

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

Wenn Sie der Anweisung ein Ausrufezeichen voranstellen, erfahren Sie, ob das Array nicht leer ist. Also in deinem Fall -

a = [1,2,3]
!a.empty?
=> true
Denny Abraham Cheriyan
quelle
27
Doppelte Verneinung? Sind Sie im Ernst?
3.
29
Er ist so nicht nicht ernst!
Alexander Bird
5
Hehe. Doppelte Negation ist nicht ideal, scheint nur in diesem speziellen Fall besser lesbar zu sein.
Denny Abraham Cheriyan
11
Das doppelte Negativ war Teil der ursprünglichen Frage "Auf nicht leeres Array prüfen". Dies beantwortet die Frage.
Mattfitzgerald
30

Vermeiden Sie any?große Arrays.

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

any? überprüft nicht die Länge, sondern durchsucht das gesamte Array nach wahrheitsgemäßen Elementen.

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? Auf der anderen Seite wird nur die Länge des Arrays überprüft.

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

Der Unterschied ist relevant, wenn Sie "spärliche" Arrays haben, die mit vielen nilWerten beginnen, wie zum Beispiel ein Array, das gerade erstellt wurde.

akuhn
quelle
In diesem Anwendungsfall ist der Unterschied nur relevant, wenn Sie "spärliche" Arrays haben, die mit vielen nilWerten beginnen, wobei "normale" Arrays any?ohne Blockrückgabe beim ersten Element vorhanden sind, sodass die Komplexität wie bei der empty?Methode
David
4

Ich werde vorschlagen, zu verwenden unlessund blankzu überprüfen, ob leer ist oder nicht.

Beispiel:

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

Dies wird 'a' leer wissen oder nicht. Wenn 'a' leer ist, wird der folgende Code nicht ausgeführt.

Dennis
quelle
4
#blank?ist Teil von Rails. Wenn sie bereits Rails verwenden, #present?ist die Negation #blank?sowieso.
Eva
0

Ich denke nicht, dass es schlecht ist, es überhaupt zu benutzen any?. Ich benutze es oft. Es ist klar und prägnant.

Wenn Sie jedoch besorgt sind, dass alle nilWerte es abwerfen, fragen Sie wirklich, ob das Array hat size > 0. In diesem Fall würde diese absolut einfache Erweiterung (NICHT optimiert, im Affenstil) Sie näher bringen.

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

Dies ist ziemlich beschreibend und fragt logisch: "Hat dieses Objekt eine Größe?". Es ist prägnant und erfordert kein ActiveSupport. Und es ist einfach, darauf aufzubauen.

Einige Extras zum Nachdenken:

  1. Dies ist nicht dasselbe wie present?bei ActiveSupport.
  2. Möglicherweise möchten Sie eine benutzerdefinierte Version für String, die Leerzeichen ignoriert (wie dies der present?Fall ist).
  3. Möglicherweise möchten Sie den Namen length?für Stringoder andere Typen, bei denen er möglicherweise aussagekräftiger ist.
  4. Möglicherweise möchten Sie es für Integerund andere NumericTypen benutzerdefinieren , damit eine logische Null zurückgegeben wird false.
Lilole
quelle