web-dev-qa-db-ja.com

カウント、サイズ、長さ... Rubyの選択肢が多すぎますか?

私はこれに関する決定的な答えを見つけることができないようであり、私はこれを「n番目のレベル」に確実に理解させたい:-)

 
 a = {"a" => "Hello"、 "b" => "World"} 
 a.count#2 
 a.size# 2 
 a.length#2 
 
 a = [10、20] 
 a.count#2 
 a.size#2 
 a.length#2 
 

どちらを使用しますか? aに複数の要素があるかどうかを知りたい場合、それは重要ではないようですが、本当の違いを確実に理解したいと思います。これは配列にも当てはまります。同じ結果が得られます。

また、カウント/サイズ/長さはActiveRecordとは異なる意味を持つことを認識しています。私は現在、純粋なRuby(1.92)に主に興味を持っていますが、ARの違いを理解したい人がいれば、それも評価されます。

ありがとう!

138
cbmeeks

配列およびハッシュの場合、 sizelength のエイリアスです。それらは同義語であり、まったく同じことを行います。

count はより用途が広い-要素または述語を取り、一致するアイテムのみをカウントできます。

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

あなたがdo n'tを提供しない場合、それは基本的に長さを呼び出すのと同じ効果があります。ただし、パフォーマンスに違いがある場合があります。

Arrayのソースコード から、ほぼ同じことを行うことがわかります。 array.lengthを実装するためのCコードは次のとおりです。

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

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..
    }
}

array.countのコードはいくつかの追加チェックを行いますが、最終的にはまったく同じコードLONG2NUM(RARRAY_LEN(ary))を呼び出します。

一方、ハッシュ( ソースコード )はcountの独自の最適化バージョンを実装していないようです。したがって、Enumerableソースコード )の実装が使用され、要素を1つずつカウントします。

一般に、要素の数をすべて知りたい場合は、lengthではなくsize(またはそのエイリアスcount)を使用することをお勧めします。


一方、ActiveRecordに関しては、重要な違いがあります。この投稿をチェックしてください:

192
Mark Byers

データベース接続を利用するアプリケーションには重大な違いがあります。

多くのORM(ActiveRecord、DataMapperなど)を使用している場合、.sizeはデータベースからすべてのアイテムを要求するクエリを生成し(「select * from mytable」)、アイテムの数を提供するという一般的な理解がある結果として、.countは単一のクエリ( 'select count(*)from mytable')を生成しますが、これはかなり高速です。

これらのORMは非常に一般的であるため、私は最小限の驚きの原則に従います。一般に、既にメモリに何かがある場合は.sizeを使用し、コードがデータベース(またはAPIを介した外部サービス)へのリクエストを生成する場合は.countを使用します。

10
stef

ほとんどの場合(例: Array または Stringsizelengthの-​​aliasです。

countは、通常 Enumerable から派生し、オプションの述語ブロックを取ることができます。したがって、enumerable.count {cond}は[大体] (enumerable.select {cond}).lengthです-一致する述部の数が必要なだけなので、もちろん中間構造をバイパスできます。

注:ブロックが指定されていない場合、または可能であればcountに短絡している場合、lengthforces列挙の評価かどうかはわかりません。

編集(そしてMarkの回答のおかげ!):countブロックなし(少なくとも配列の場合)- しない評価を強制します。いずれにしても、述語なしで評価を強制するのが本当に理にかなっているなら、正式な振る舞いがなければ、他の実装では「オープン」だと思います。

7
user166390

http://blog.hasmanythrough.com/2008/2/27/count-length-size で良いアンウェアを見つけました

ActiveRecordには、関連付けに含まれるレコードの数を調べる方法がいくつかあり、それらの動作方法には微妙な違いがあります。

post.comments.count-SQL COUNTクエリで要素の数を決定します。関連する要素のサブセットのみをカウントする条件を指定することもできます(例::conditions => {:author_name => "josh"})。関連付けにカウンターキャッシュを設定すると、#countは新しいクエリを実行する代わりに、キャッシュされた値を返します。

post.comments.length-これは常に関連付けの内容をメモリにロードし、ロードされた要素の数を返します。これは、関連付けが以前にロードされ、新しいコメントが別の方法で作成された場合(たとえば、post.comments.create(...)ではなくComment.create(...))に更新を強制しないことに注意してください。

post.comments.size-これは、前述の2つのオプションの組み合わせとして機能します。コレクションが既にロードされている場合、#lengthを呼び出すのと同じようにコレクションの長さを返します。まだロードされていない場合は、#countを呼び出すようなものです。

また、私は個人的な経験があります:

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

.length.count、および.sizeのような配列内の要素の数を調べる方法はいくつかあります。ただし、array.sizeよりもarray.countを使用することをお勧めします。 .sizeはパフォーマンスが優れているためです。

2
Venkat M

Mark Byersの回答にさらに追加します。 Rubyでは、メソッドarray.sizeArray#length メソッドのエイリアスです。これら2つの方法のいずれを使用しても、技術的な違いはありません。おそらくパフォーマンスにも違いは見られないでしょう。ただし、array.countも同じ仕事をしますが、いくつかの追加機能があります Array#count

何らかの条件に基づいて、要素の総数を取得するために使用できます。 Countは、次の3つの方法で呼び出すことができます。

Array#count#配列の要素数を返します

Array#count n#配列に値nを持つ要素の数を返す

Array#count {| i | i.even?}各要素配列で呼び出された条件に基づいてカウントを返します

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

ここでは、3つの方法すべてが同じ仕事をします。ただし、countが興味深いのはここです。

配列に値2が含まれる配列要素の数を調べたいとしましょう

array.count 2    # => 3

配列には、値が2の合計3つの要素があります。

今、私は4より大きいすべての配列要素を見つけたい

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

配列には、4よりも大きい合計6つの要素があります。

countメソッドに関する情報が提供されることを願っています。

1
Prabhakar