Sayı, boyut, uzunluk… Ruby'de çok fazla seçenek mi var?


140

Bu konuda kesin bir cevap bulamıyorum ve ben bunu "n'th level" için anlamak emin olmak istiyorum :-)

    a = {"a" => "Merhaba", "b" => "Dünya"}
    a.count # 2
    a. boyut # 2
    uzunluk # 2

    a = [10, 20]
    a.count # 2
    a. boyut # 2
    uzunluk # 2

Peki hangisi kullanılacak? A'nın birden fazla öğesi olup olmadığını bilmek istersem önemli görünmüyor, ancak gerçek farkı anladığımdan emin olmak istiyorum. Bu, diziler için de geçerlidir. Aynı sonuçları alıyorum.

Ayrıca, ActiveRecord ile sayım / boyut / uzunlukların farklı anlamları olduğunun farkındayım. Ben çoğunlukla şu anda saf Ruby (1.92) ile ilgileniyorum ama kimse AR fark yapar chime ister de takdir edilecektir.

Teşekkürler!


5
Karşılaştığınız olaya bazen TMTOWTDI denir : Bunu Yapmanın Birden Fazla Yolu Var. Bu slogan Perl topluluğundan geliyor ve Perl Ruby üzerindeki etkilerinden biri.
Andrew Grimm

bunlar genellikle birbirlerinin takma adlarıdır - aynı şeyi yaparlar. Unutmamanız gereken bir yöntem vardır: Array#nitemsbir dizideki NIL olmayan öğelerin sayısını döndürür. Ama bu artık Ruby 1.9'da mevcut değil
Tilo

Yanıtlar:


194

Diziler ve karmalar sizeiçin bir takma addır length. Eşanlamlıdırlar ve aynı şeyi yaparlar.

count daha çok yönlüdür - bir öğe alabilir veya yalnızca eşleşen öğeleri belirleyebilir ve sayabilir.

> [1,2,3].count{|x| x > 2 }
=> 1

Eğer nereye yok temelde uzunluğu arayarak aynı etkiye sahiptir saymak için bir parametre sunar. Yine de bir performans farkı olabilir.

Biz de görebileceğiniz Array için kaynak kodu neredeyse aynı şeyleri yapmak. İşte uygulanması için C kodu array.length:

static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}

Ve işte ilgili kısım array.count:

static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long n = 0;

    if (argc == 0) {
        VALUE *p, *pend;

        if (!rb_block_given_p())
            return LONG2NUM(RARRAY_LEN(ary));

        // etc..
    }
}

İçin kod array.countbirkaç ekstra kontroller yapar ama sonunda kodun aynısını çağırır: LONG2NUM(RARRAY_LEN(ary)).

Öte yandan karmalar ( kaynak kodu ) kendi optimize edilmiş sürümlerini uygulamıyor gibi görünmektedir, countbu nedenle Enumerable( kaynak kodu ) ' dan gelen uygulama kullanılır, bu da tüm öğeler üzerinde yinelenir ve bunları tek tek sayar.

Genel olarak length, kaç elementin birlikte olduğunu bilmek sizeyerine (veya takma adını ) kullanmanızı öneririm count.


ActiveRecord ile ilgili olarak , önemli farklılıklar vardır. bu yazıyı kontrol et:


10

Veritabanı bağlantılarından yararlanan uygulamalar için çok önemli bir fark vardır.

Birçok ORM (ActiveRecord, DataMapper, vb.) Kullanırken genel anlayış, .size'nin veritabanındaki tüm öğeleri isteyen ('mytable'dan' seçin) bir sorgu üretip size öğe sayısını vermesidir. bununla birlikte, .count oldukça hızlı olan tek bir sorgu ('mytable'dan sayım (*) seçin') oluşturur.

Bu ORM'ler çok yaygın olduğu için en az şaşkınlık ilkesini izliyorum. Genelde zaten bellekte bir şey varsa, o zaman .size kullanın ve kodum bir veritabanı (veya bir API aracılığıyla harici hizmet) için bir istek üretecek .count kullanıyorum.


1
Bununla dikkate alınması gereken bir şey var counter_cache. Bir tablonuz varsa foove has_many ise bar, bir oluşturulduğunda / yok edildiğinde güncellenen fooadlı bir sütuna sahip olursunuz . Kullanılması ne sütunda ki (aslında herhangi sorgulama olmadan çekler ). önbelleğin amacını yenecek gerçek sorguyu yapar. bars_countbarfoo.bars.sizebarsfoo.bars.count
Dudo

7

Çoğu durumda (örneğin in Dizi veya dize ) sizebir olduğunu takma için length.

countnormalde Numaralandırılabilir'den gelir ve isteğe bağlı bir yüklem bloğu alabilir. Böylece enumerable.count {cond}[kabaca] (enumerable.select {cond}).length- elbette sadece eşleşen tahminlerin sayısına ihtiyaç duyduğu için ara yapıyı atlayabilir.

Not: Emin değilim eğer count kuvvetler için bir sıralamanın değerlendirme bloğu belirtilen değilse ya da kısa devre durumunda lengthmümkünse.

Düzenleme (ve Mark'ın cevabı sayesinde!): count Bir blok olmadan (en azından Diziler için) bir değerlendirmeyi zorlamaz . Resmi davranışlar olmadan, eğer bir yüklem olmadan bir değerlendirmeyi zorlamak gerçekten de mantıklıysa, diğer uygulamalar için "açık" olduğunu düşünüyorum.


5

Http://blog.hasmanythrough.com/2008/2/27/count-length-size adresinde iyi bir yazılım buldum

ActiveRecord'da, bir ilişkilendirmede kaç kaydın bulunduğunu bulmanın birkaç yolu vardır ve bunların nasıl çalıştığında bazı küçük farklılıklar vardır.

post.comments.count - SQL COUNT sorgusu olan öğe sayısını belirleyin. İlişkili öğelerin yalnızca bir alt kümesini saymak için koşulları da belirtebilirsiniz (örneğin: condition => {: author_name => "josh"}). İlişkilendirme için bir karşı önbellek ayarlarsanız, #count yeni bir sorgu yürütmek yerine bu önbelleğe alınan değeri döndürür.

post.comments.length - Bu, ilişkilendirmenin içeriğini her zaman belleğe yükler, sonra yüklenen öğelerin sayısını döndürür. İlişkilendirme daha önce yüklenmişse ve daha sonra başka bir yolla yeni yorumlar oluşturulmuşsa (örneğin, post.comments.create (...) yerine Comment.create (...)) bu güncellemeyi zorlamayacağını unutmayın.

post.comments.size - Bu, önceki iki seçeneğin bir kombinasyonu olarak çalışır. Koleksiyon zaten yüklenmişse, #length çağrısı gibi uzunluğunu döndürür. Henüz yüklenmediyse, #count çağrısı gibidir.

Ayrıca kişisel bir deneyimim var:

<%= h(params.size.to_s) %> # works_like_that !
<%= h(params.count.to_s) %> # does_not_work_like_that !

2

Biz gibi bir dizideki kaç unsurları öğrenmek için birkaç yol vardır .length, .countve .size. Ancak, kullanmak array.sizeyerine kullanmak daha iyidir array.count. Çünkü .sizeperformansta daha iyidir.


1

Mark Byers yanıtına daha fazla şey ekleme. Ruby'de yöntem Array # length yöntemine array.sizebir takma addır . Bu iki yöntemden herhangi birinin kullanımında teknik bir fark yoktur. Muhtemelen performansta da bir fark görmeyeceksiniz. Bununla birlikte, array.countaynı işi yapar, ancak bazı ekstra işlevlerle Array # count

Bazı koşullara göre toplam eleman elde etmek için kullanılabilir. Sayım üç şekilde çağrılabilir:

Dizi # sayısı # Dizi'deki öğe sayısını döndürür

Dizi # sayısı n # Dizi'de n değerine sahip öğelerin sayısını döndürür

Dizi # sayımı {| i | i.even?} Her öğe dizisinde çağrılan koşula göre sayım döndürür

array = [1,2,3,4,5,6,7,4,3,2,4,5,6,7,1,2,4]

array.size     # => 17
array.length   # => 17
array.count    # => 17

Burada her üç yöntem de aynı işi yapıyor. Ancak burada countilginç olur.

Diyelim ki dizi değeri 2 ile dizi dizi öğeleri bulmak istiyorum

array.count 2    # => 3

Dizi, değeri 2 olan toplam üç öğeye sahiptir.

Şimdi, tüm dizi elemanlarını 4'ten büyük bulmak istiyorum

array.count{|i| i > 4}   # =>6

Dizi, 4'ten fazla olan toplam 6 öğeye sahiptir.

Umarım countyöntem hakkında bilgi verir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.