web-dev-qa-db-ja.com

空でない配列をチェックします。

any?メソッドを使用して、配列がではない空かどうかをチェックするのは悪いことですか?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

それともunless a.empty?を使うほうがいいですか?

162
sivabudh

any?は、場合によってはnot empty?と同じではありません。

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

ドキュメントから:

ブロックが与えられていない場合、Rubyは{| obj |の暗黙のブロックを追加します。 (コレクションメンバーの少なくとも1つがfalseでもnilでもない場合は、any?はtrueを返します)。

212

値がtrueと評価される配列、またはその値が空であるかどうかの違い。

メソッドempty?はArrayクラスから来ています
http://Ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

配列に何かが含まれているかどうかをチェックするために使用されます。これには、nilやfalseなど、falseと評価されるものが含まれます。

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

メソッドany?はEnumerableモジュールから来ています。
http://Ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

これは、配列内の "any"値がtrueに評価されるかどうかを評価するために使用されていました。これに似た方法はどれもありませんか?すべて?そして一つ?どこで彼らはただ真実が何回評価されることができるかについて確かめるためにチェックするだけです。これは、配列内で見つかった値の数とは関係ありません。

ケース1

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

ケース2

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

ケース3

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

ステートメントの先頭に感嘆符を付けると、配列が空ではないかどうかがわかります。だからあなたの場合 -

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

大きな配列の場合はany?を避けてください。

  • any?O(n)です
  • empty?O(1)です

any?は長さをチェックしませんが、実際には真の要素について配列全体をスキャンします。

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?は配列の長さだけをチェックします。

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

例えば、作成されたばかりの配列のように、たくさんのnil値で始まる "疎な"配列がある場合、違いは重要です。

22
akuhn

unlessblankを使って空かどうかを確認することをお勧めします。

例:

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

これは「空」かどうかを知るでしょう。 'a'が空白の場合、以下のコードは実行されません。

4
Dennis

any?を使うのは悪いことではないと思います。私はそれをたくさん使います。それは明確かつ簡潔です。

ただし、すべてのnilname__の値でそれが無効になることを心配している場合は、配列にsize > 0があるかどうかを実際に確認しています。そのような場合は、この単純な拡張機能(最適化されていない、サルスタイル)を使用すると、親切になります。

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

これはかなり説明的で、「このオブジェクトにはサイズがありますか?」と論理的に尋ねます。そしてそれは簡潔です、そしてそれはActiveSupportを必要としません。そして上に構築するのは簡単です。

考慮すべき点がいくつかあります。

  1. これはActiveSupportのpresent?と同じではありません。
  2. 空白を無視する(present?のように)Stringname__のカスタムバージョンが必要な場合があります。
  3. Stringname__の場合はlength?という名前にすることをお勧めします。
  4. Integername__および他のNumericname__型にはカスタムにして、論理ゼロがfalsename__を返すようにすることをお勧めします。
0
lilole