Ruby - dizi testi


265

Doğru yol nedir:

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

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

veya içindeki öğelerin sayısını almak için?


7
Gerçek bir dizi mi yoksa sadece dizi benzeri bir şey mi istiyorsunuz?
Kathy Van Stone

1
Ruby'de tip güvenliği yoktur. Değişkeninizin dizi olup olmadığı konusunda endişelenmeyin. Yöntem, bunun olduğunu varsaymalı ve devam etmeli ve üzerinde saymayı
aramalıdır

Daha deyimsel Ruby için lütfen zgchurch ve DigitalRoss'un cevaplarını okuyun.
DanT

Yanıtlar:


516

Muhtemelen kullanmak istiyorsunuz kind_of().

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

31
Ayrıca is_a?ve var instance_of?. Bkz. Stackoverflow.com/questions/3893278/…
Nathan Long

2
Tür denetimi Java içindir. Devam edin ve değişkeni sayın. Yöntemin beklendiği gibi çalıştığından emin olmak için birim testleri yazın.
user132447 21:12

14
@ user132447 aslında java türü güvenlidir, bu yüzden herhangi bir türü kontrol etme konusunda endişelenmenize gerek yoktur
grinch

8
Bunu Ruby gibi bir dilde iyi bir uygulama olduğunu düşünmediğim için şimdi reddettim. @Zgchurch'ün cevabı açıkça soruya çok daha deyimsel bir yaklaşımdır. Bu gibi durumlarda, körü körüne bir av tüfeği vermek yerine OP'nin ne anlama geldiğini anlamanın çok daha mantıklı olduğunu düşünüyorum ...
Per Lundberg

1
Neden kind_of?()diğer çözümlerden daha fazla kullanmak istersiniz ? Cevabınızın diğerlerine göre faydaları hakkında bazı açıklamalar gelecekteki okuyucular için yararlı olacaktır.
AlbertEngelB

148

Dizi olması gerektiğinden emin misiniz ? Kullanılacak mümkün olabilir respond_to?(method)kodunuzu mutlaka diziler (belki başka enumberable şey) değildir benzer şeyler için çalışacak böylece. Aslında bir ihtiyacınız varsa array, Array#kind\_of?yöntemi açıklayan yazı en iyisidir.

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

1
Bu durumda bir Dizi olacağından eminim. Ama bu yöntemi de bilmek güzel. +1
BuddyJoe

İlginç bir fikir, veri yapısı üzerinde push / pop kullanıyorum. Dizilerin dışında bir şey bu yöntemlere yanıt verir mi?
Drew

3
Daha dizi benzeri bir şey istiyorsanız, isteyebilirsiniz respond_to?(:to_ary).
Andrew Grimm

21
Genel olarak, bu OO gelişimi için iyi bir uygulamadır. Birisinin temelde söylediği yeri okudum: Nesnelerinizde yöntemler çağırdığınızı hayal etmeyin. Onlara mesaj gönderiyorsunuz. Bir nesne iletinize nasıl yanıt vereceğini bilirse, hangi sınıf olduğunu ya da buna ad verilmiş bir yöntemi olup olmadığını ya da method_missing yoluyla dinamik olarak bir yanıt oluşturup oluşturmadığını umursamazsınız. Önemli olan, mesajınıza cevap verebilir mi? Bu fonksiyon ve uygulamanın daha iyi soyutlanmasını sağlar. Daha sonra kullandığınız nesneyi, yine de doğru yanıt verdiği sürece değiştirebilirsiniz.
Nathan Long

2
Bu konuda tek sorun, bir şey dizine yinelenebilir olup olmadığını kontrol etmek istiyorum, bu yüzden diziler, bağlantılı listeler, vb serin olurdu, ama hashes gibi anahtar değeri mağazalar istemiyorum?
Colton Voege

58

Array,Tek bir seviyeye dönüştürmek için sadece bir dönüşümü test etmek yerine, Array,kodunuzun yalnızca bir durumu ele alması gerekir.

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

Yakut bir şey olmadığını bilmek istiyorum neden bir tahmin alarak bir nesne ya da nesnelerin bir Array alabilir bir API uyumlu hale getirmek için çeşitli yollar vardır, bu yüzden olduğu bir Dizi, bir önerim var.

Uyarısı operatörü sihirli bir sürü içerir yukarı bakmak, ya da sadece çağırabilir Array(something)gerekirse Dizi sarıcı ekleyecek olan. [*something]Bu bir davaya benziyor .

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

Veya, parametre bildiriminde uyarıyı kullanabilir ve sonra .flattensize farklı bir koleksiyoncu verebilirsiniz . (Bu konuda .flattenyukarıda da arayabilirsiniz .)

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]"

Ve teşekkürler gregschlom , bazen sadece kullanmak daha hızlıdır Array(x)çünkü zaten bir olduğunda Arrayyeni bir nesne yaratmaya gerek yoktur.


Yani tek bir öğe ise, içinde tek bir öğe bulunan bir dizi haline geldiğini mi söylüyorsunuz?
BuddyJoe

Evet ve zaten bir dizi ise, ikinci bir dizi sarıcı eklemeden onu korur.
DigitalRoss

2
Unutma: [*nil] => []. Böylece boş bir dizi elde edebilirsiniz.
Christopher Oezbek

3
Kullanmak Array(foo)çok daha verimli[*foo]
gregschlom

23

[1,2,3].is_a? Array doğru olarak değerlendirir.


1
Bu, neredeyse yedi yıldır sitede bulunan cevaplara ne katıyor?
Martin Tournoij

6
@Carpetsmoker bu yazının tümünde referans is_a?olan kısa bir cevap yok . En yakın olanı [1,2,3].is_a? Enumerable. Bu cevaba sahip olmanın hala değerli olduğunu düşünüyorum.
dipole_moment

4
Bilirsiniz .. aslında haklısınız ... Bunu daha önce orada gördüğüme yemin edebilirdim: - / Bir oy verin!
Martin Tournoij

16

Bazı öğeler konseptine sahip bir şeyin peşindesiniz. Böylece olup olmadığını görmenizi tavsiye ederim Enumerable. Bu aynı zamanda varlığını da garanti eder #count.

Örneğin,

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

ederken, unutmayın size, lengthve countdiziler için bütün iş, count(örneğin, - Burada doğru anlamı 'abc'.lengthve 'abc'.sizehem iş, ama 'abc'.countböyle iş yapmaz).

Dikkat: bir dize is_a? Numaralandırılabilir, bu yüzden belki de bu istediğiniz şey değildir ... dizi benzeri bir nesne kavramınıza bağlıdır.


11

Deneyin:

def is_array(a)
    a.class == Array
end

EDIT : Diğer cevap benimkinden çok daha iyi.


6

Ayrıca kullanmayı düşünün Array(). Gönderen Yakut Topluluk Stil Rehberi :

Dizi olarak değerlendirmek istediğiniz bir değişkenle uğraşırken açık Dizi kontrolü veya [* var] yerine Array () kullanın, ancak bunun bir dizi olduğundan emin değilsiniz.

# 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) }

Bu to_a, yeni diziye eklenen her bağımsız değişken için çağrıldığı için bir Hash'i geçerken beklenmedik sonuçlar üretecektir , bu nedenle Array({id: 100})döner[[:id, 100]]
brent
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.