Sprawdź, czy tablica nie jest pusta: jakaś?


191

Czy źle jest sprawdzić, czy tablica nie jest pusta za pomocą any?metody?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

A może lepiej użyć unless a.empty??

Odpowiedzi:


248

any?to nie to samo co not empty?w niektórych przypadkach.

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

Z dokumentacji:

Jeśli blok nie zostanie podany, Ruby dodaje domyślny blok {| obj | obj} (czy jest jakiś? zwróci true, jeśli co najmniej jeden z elementów kolekcji nie ma wartości false lub zero).


8
Czy jest jakaś funkcja przeciwna do empty??
RocketR

12
@RocketR możesz chcieć sprawdzić present?metodę.
dantheta

15
@dantastic #present?jest przeznaczony tylko dla Railsów. W czystym Ruby dostaniesz NoMethodError: undefined method 'present?' for Array.
RocketR

6
Nie tylko Rails, Active Support może być używany bez szyn, wystarczy require 'activesupport'.
Sergio A.,

83

Różnica między tablicą oceniającą jej wartości, truea jeśli jest pusta.

Metoda empty?pochodzi z klasy Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Służy do sprawdzania, czy tablica zawiera coś, czy nie. Obejmuje to rzeczy, które oceniają false, takie jak nili false.

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

Metoda any?pochodzi z modułu Enumerable.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

Służy do oceny, czy „dowolna” wartość w tablicy ma wartość true. Podobne metody do tego są none?, all?a one?gdzie oni wszyscy po prostu sprawdzić, ile razy można ocenić prawdziwe. co nie ma nic wspólnego z liczbą wartości znalezionych w tablicy.

przypadek 1

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

przypadek 2

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

przypadek 3

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

31

Prefiks instrukcji wykrzyknikiem informuje, czy tablica nie jest pusta. Więc w twoim przypadku -

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

27
Podwójna negacja? Mówisz poważnie?
3lvis

29
On nie jest taki poważny!
Alexander Bird

5
Hehe Podwójna negacja nie jest idealna, po prostu wydaje się bardziej czytelna w tym konkretnym przypadku.
Denny Abraham Cheriyan

12
Podwójny negatyw był częścią pierwotnego pytania „Sprawdź, czy tablica nie jest pusta”. To odpowiada na pytanie.
mattfitzgerald

30

Unikaj w any?przypadku dużych tablic.

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

any? nie sprawdza długości, ale faktycznie skanuje całą tablicę w poszukiwaniu prawdziwych elementów.

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? z drugiej strony sprawdza tylko długość tablicy.

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

Różnica jest istotna, jeśli masz „rzadkie” tablice, które zaczynają się od wielu nilwartości, takich jak na przykład właśnie utworzona tablica.


W tym przypadku użycia różnica jest istotna tylko wtedy, gdy masz „rzadkie” tablice, które zaczynają się od wielu nilwartości, z „normalnymi” tablicami any?bez bloków zwracających pierwszy element, więc złożoność jest nadal równa O (1), podobnie jak empty?metoda
David Costa

4

Sugeruję używanie unlessi blanksprawdzanie, czy jest puste, czy nie.

Przykład:

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

Będzie to oznaczać „puste” lub nie. Jeśli „a” jest puste, poniższy kod nie będzie działał.


4
#blank?jest częścią Rails. Jeśli już używają Railsów, #present?to i #blank?tak jest zaprzeczeniem .
Eva,

0

Nie sądzę, żeby korzystanie any?z niego było złe . Często go używam. To jasne i zwięzłe.

Jeśli jednak obawiasz się, że wszystkie nilwartości ją wyrzucają, to naprawdę pytasz, czy tablica ma size > 0. W takim przypadku to martwe proste rozszerzenie (NIE zoptymalizowane, w stylu małpim) zbliży cię.

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

Jest to dość opisowe, logicznie pytające „czy ten obiekt ma rozmiar?”. Jest zwięzły i nie wymaga ActiveSupport. I łatwo go zbudować.

Kilka dodatków do przemyślenia:

  1. To nie to samo, co present?z ActiveSupport.
  2. Możesz potrzebować niestandardowej wersji String, która ignoruje białe znaki (podobnie jak present?robi).
  3. Może chcesz nazwę length?dla Stringlub innych rodzajów gdzie może być bardziej opisowe.
  4. Możesz chcieć mieć niestandardowe dla Integeri innych Numerictypów, aby zwracało się logiczne zero false.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.