Periksa array tidak kosong: ada?

191

Apakah buruk untuk memeriksa apakah array tidak kosong dengan menggunakan any?metode?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

Atau lebih baik digunakan unless a.empty??

sivabudh
sumber

Jawaban:

248

any?tidak sama dengan not empty?dalam beberapa kasus.

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

Dari dokumentasi:

Jika blok tidak diberikan, Ruby menambahkan blok implisit {| obj | obj} (itu ada? akan mengembalikan true jika setidaknya salah satu anggota koleksi tidak salah atau nihil).

Marcel Jackwerth
sumber
8
Apakah ada fungsi yang berlawanan empty??
RocketR
12
@RocketR Anda mungkin ingin present?metode checkout .
dantheta
15
@dantastic #present?hanya untuk Rails. Di Ruby murni Anda akan mendapatkan NoMethodError: undefined method 'present?' for Array.
RocketR
6
Bukan hanya Rails saja, Dukungan Aktif dapat digunakan tanpa rel, hanya perlu require 'activesupport'.
Sergio A.
83

Perbedaan antara array yang mengevaluasi nilainya ke trueatau jika kosong.

Metode ini empty?berasal dari kelas Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Ini digunakan untuk memeriksa apakah array berisi sesuatu atau tidak. Ini termasuk hal-hal yang dievaluasi false, seperti nildan false.

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

Metode ini any?berasal dari modul Enumerable.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

Ini digunakan untuk mengevaluasi jika nilai "any" dalam array dievaluasi true. Metode serupa untuk ini adalah none?, all?dan one?, di mana mereka semua hanya memeriksa untuk melihat berapa kali benar dapat dievaluasi. yang tidak ada hubungannya dengan hitungan nilai yang ditemukan dalam array.

kasus 1

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

kasus 2

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

kasus 3

>> a = [true, true]
=> [true, true]
>> a.any?
=> true
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> false
Pendorong Poligon
sumber
31

Awalan pernyataan dengan tanda seru akan memberi tahu Anda apakah array tidak kosong. Jadi dalam kasus Anda -

a = [1,2,3]
!a.empty?
=> true
Denny Abraham Cheriyan
sumber
27
Negasi ganda? Apakah kamu serius?
3lvis
29
Dia tidak begitu serius!
Alexander Bird
5
Hehe. Negasi ganda tidak ideal, sepertinya lebih mudah dibaca dalam kasus khusus ini.
Denny Abraham Cheriyan
12
Dobel negatif adalah bagian dari pertanyaan awal "Periksa array tidak kosong". Ini menjawab pertanyaan.
mattfitzgerald
30

Hindari any?untuk array besar.

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

any? tidak memeriksa panjang tetapi sebenarnya memindai seluruh array untuk elemen yang benar.

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? di sisi lain memeriksa panjang array saja.

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

Perbedaannya relevan jika Anda memiliki array "jarang" yang dimulai dengan banyak nilnilai, seperti misalnya array yang baru saja dibuat.

akuhn
sumber
Dalam kasus penggunaan ini perbedaan hanya relevan jika Anda memiliki array "jarang" yang dimulai dengan banyak nilnilai, dengan array "normal" any?tanpa pengembalian blok pada elemen pertama, sehingga kompleksitasnya masih O (1) seperti empty?metode
David Costa
4

Saya akan menyarankan menggunakan unlessdan blankmemeriksa kosong atau tidak.

Contoh:

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

Ini akan tahu 'a' kosong atau tidak. Jika 'a' kosong maka kode di bawah ini tidak akan berjalan.

Dennis
sumber
4
#blank?adalah bagian dari Rails. Jika mereka sudah menggunakan Rails, #present?bagaimanapun negasinya #blank?.
Eva
0

Saya tidak berpikir itu buruk untuk digunakan any?sama sekali. Saya sering menggunakannya. Jelas dan ringkas.

Namun jika Anda khawatir tentang semua nilnilai yang dibuang, maka Anda benar-benar bertanya apakah array memiliki size > 0. Dalam hal ini, ekstensi sederhana yang mati ini (TIDAK dioptimalkan, gaya monyet) akan membuat Anda dekat.

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

Ini cukup deskriptif, secara logis bertanya "apakah objek ini memiliki ukuran?". Dan ringkas, dan tidak memerlukan ActiveSupport. Dan mudah untuk dibangun.

Beberapa tambahan untuk dipikirkan:

  1. Ini tidak sama dengan present?dari ActiveSupport.
  2. Anda mungkin menginginkan versi khusus untuk String, yang mengabaikan spasi putih (seperti present?halnya).
  3. Anda mungkin menginginkan nama length?untuk Stringatau jenis lain yang lebih deskriptif.
  4. Anda mungkin ingin kustom untuk Integerdan Numericjenis lainnya , sehingga nol logis kembali false.
lilole
sumber