Ruby-配列のテスト


265

正しい方法は何ですか:

is_array("something") # => false         (or 1)

is_array(["something", "else"]) # => true  (or > 1)

またはその中のアイテムの数を取得するには?


7
実際の配列、または単に配列のようなものが必要ですか?
キャシーヴァンストーン

1
Rubyには型保証はありません。変数が配列であることを気にしないでください。メソッドはそれがそうであると想定し、カウントを呼び出す必要があります:my_array.count
user132447

より慣用的なRubyについては、zgchurchおよびDigitalRossによる回答を読んでください。
DanT 2015年

回答:


516

あなたはおそらく使いたいでしょうkind_of()

>> s = "something"
=> "something"
>> s.kind_of?(Array)
=> false
>> s = ["something", "else"]
=> ["something", "else"]
>> s.kind_of?(Array)
=> true

31
is_a?ともありinstance_of?ます。stackoverflow.com/questions/3893278/…を
Nathan Long

2
型チェックはJava用です。先に進んで、変数のcountを呼び出します。単体テストを作成して、メソッドが期待どおりに機能することを確認します。
user132447 2012年

14
あなたはどんなタイプのチェックを心配する必要はありませんので、@ user132447は、実際にはJavaの型安全である
グリンチ

8
これはRubyのような言語では良い習慣だとは思わないので、今は反対票を投じました。@zgchurchによる回答は、明らかに質問に対するはるかに慣用的なアプローチです。このような場合、盲目的にショットガンを与えるよりも、OPの意味を理解してみる方がはるかに理にかなっていると思います...
Per Lundberg

1
なぜkind_of?()他のソリューションよりも使いたいのですか?他の人に対するあなたの答えの利点に関するいくつかの説明は、将来の読者にとって役立つでしょう。
AlbertEngelB

148

配列である必要がありますか?あなたはrespond_to?(method)あなたのコードが必ずしも配列ではない(おそらく他のenumberableなものである)類似したもののために機能するように使うことができるかもしれません。実際にが必要な場合はarrayArray#kind\_of?メソッドを説明する投稿が最適です。

['hello'].respond_to?('each')

1
この場合、それは配列になると確信しています。しかし、この方法も知っておくと便利です。+1
BuddyJoe、2009年

興味深いアイデアですが、私はデータ構造でプッシュ/ポップを使用しています。配列以外のものはこれらのメソッドに応答しますか?
ドリュー

3
配列のようなものが必要な場合は、が必要になる場合がありますrespond_to?(:to_ary)
Andrew Grimm

21
一般に、これはOO開発の良い習慣です。私は誰かが基本的に言ったところを読みました:あなたがあなたのオブジェクトのメソッドを呼び出していると想像しないでください。あなたは彼らにメッセージを送っています。オブジェクトがメッセージへの応答方法を知っている場合、オブジェクトがどのクラスであるか、オブジェクトにその名前のメソッドがあるかどうか、またはmethod_missingを介して動的に応答を作成しているかどうかは関係ありません。重要なことは、それがあなたのメッセージに応答できるかどうかです。これにより、機能と実装の抽象化が向上します。後で正しく応答する限り、後で使用するオブジェクトを変更できます。
ネイサンロング、

2
これの唯一の問題は、何かがインデックス付きの反復可能かどうかを確認したいということです。そのため、配列、リンクリストなどはかっこいいですが、ハッシュのようなキー値ストアは必要ありませんか?
Colton Voege 2017年

58

Array,1レベルに変換したものを単にテストする代わりにArray,、コードは1つのケースのみを処理する必要があります。

t = [*something]     # or...
t = Array(something) # or...
def f *x
    ...
end

Rubyには、オブジェクトまたはオブジェクトの配列を取ることができるAPIを調和させるさまざまな方法があります。そのため、何か配列であるかどうかを知りたい理由を推測して、私は提案します。

スプラットのオペレータは、魔法の多くが含まれていますが、調べることができます、またはあなただけ呼び出すことができArray(something)、必要に応じて配列ラッパーを追加しますました。これ[*something]は、この1つの場合と同様です。

def f x
  p Array(x).inspect
  p [*x].inspect
end
f 1         # => "[1]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"

または、パラメーター宣言でスプラットを使用してから.flatten、別の種類のコレクターを提供することもできます。(さらに言えば、.flatten上記も呼び出すことができます。)

def f *x
  p x.flatten.inspect
end         # => nil
f 1         # => "[1]"
f 1,2       # => "[1, 2]"
f [1]       # => "[1]"
f [1,2]     # => "[1, 2]"
f [1,2],3,4 # => "[1, 2, 3, 4]"

そして、gregschlomのおかげでArray(x)Arrayそれがすでにある場合は新しいオブジェクトを作成する必要がないため、使用するだけで高速になることがあります。


それで、それが単一のアイテムである場合、それは単一のアイテムを含む配列になると言っていますか?
BuddyJoe、2009年

はい、すでに配列である場合は、2番目の配列ラッパーを追加せずに保持します。
DigitalRoss

2
忘れないでください[*nil] => []。したがって、空の配列になる可能性があります。
クリストファーOezbek 2014年

3
を使用する方Array(foo)がはるかに効率的[*foo]
gregschlom

23

[1,2,3].is_a? Array trueと評価されます。


1
これは、ほぼ7年間サイトにある回答に何を追加しますか?
Martin Tournoij 2016年

6
@Carpetsmoker is_a?このスレッド全体を参照する簡潔な答えはありません。最も近いのは[1,2,3].is_a? Enumerableです。私はまだこの答えを持つ価値があると思います。
dipole_moment 2016年

4
あなたが知っている..あなたは実際に正しい...私は私が以前にそれを見たと誓ったかもしれない:-/賛成票を持っている!
Martin Tournoij 2016年

16

アイテムのコンセプトがあるものを求めているようですね。したがって、そうであるかどうかを確認することをお勧めしEnumerableます。それはの存在も保証し#countます。

例えば、

[1,2,3].is_a? Enumerable
[1,2,3].count

一方で、それを注意しsizelengthそしてcount配列のためのすべての作業は、count(例えば、 -ここでは、右の意味である'abc'.length'abc'.sizeの両方の仕事は、しかし、'abc'.countそのような作業をしません)。

注意:文字列is_a?列挙可能なので、おそらくこれはあなたが望むものではありません...オブジェクトのような配列の概念に依存します。



6

の使用も検討してくださいArray()Rubyのコミュニティスタイルガイド

配列として扱いたい変数を処理する場合、明示的な配列チェックまたは[* var]ではなくArray()を使用しますが、それが配列であるかどうかはわかりません。

# bad
paths = [paths] unless paths.is_a? Array
paths.each { |path| do_something(path) }

# bad (always creates a new Array instance)
[*paths].each { |path| do_something(path) }

# good (and a bit more readable)
Array(paths).each { |path| do_something(path) }

to_a新しい配列に追加された各引数に対してが呼び出されるため、ハッシュを渡すと予期しない結果が生成されArray({id: 100})ます。そのため、戻り値[[:id, 100]]
brent
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.