Який правильний шлях:
is_array("something") # => false (or 1)
is_array(["something", "else"]) # => true (or > 1)
або отримати кількість предметів у ньому?
Який правильний шлях:
is_array("something") # => false (or 1)
is_array(["something", "else"]) # => true (or > 1)
або отримати кількість предметів у ньому?
Відповіді:
Ви, мабуть, хочете використовувати kind_of()
.
>> s = "something"
=> "something"
>> s.kind_of?(Array)
=> false
>> s = ["something", "else"]
=> ["something", "else"]
>> s.kind_of?(Array)
=> true
kind_of?()
над іншими рішеннями? Деякі пояснення щодо переваг вашої відповіді над іншими допоможуть майбутнім читачам.
Ви впевнені, що це повинен бути масив? Можливо, ви зможете використовувати respond_to?(method)
так, щоб ваш код працював для подібних речей, які не обов'язково є масивами (можливо, якась інша перелічна річ). Якщо вам насправді потрібен array
, то Array#kind\_of?
найкращий пост, що описує метод.
['hello'].respond_to?('each')
respond_to?(:to_ary)
.
Замість тестування Array,
справедливої конвертації того, що ви отримаєте, в однорівневий, Array,
тому ваш код повинен обробляти лише один випадок.
t = [*something] # or...
t = Array(something) # or...
def f *x
...
end
У Ruby є різні способи гармонізації API, який може приймати об’єкт або масив об'єктів, тому, здогадуючись, чому ви хочете дізнатися, чи є щось масив, у мене є пропозиція.
Оператор splat містить багато магії, яку ви можете шукати, або ви можете просто зателефонувати, Array(something)
яка додасть обгортку Array, якщо потрібно. Це схоже на [*something]
цей випадок.
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
, не потрібно створювати новий об’єкт.
[*nil] => []
. Тож у вас може виникнути порожній масив.
Array(foo)
набагато ефективніше ніж[*foo]
[1,2,3].is_a? Array
оцінює до істинного.
is_a?
у цілій темі. Найближчий - a [1,2,3].is_a? Enumerable
. Я все ще думаю, що варто відповісти на цю відповідь.
Це здається, що ти шукаєш щось, що має певну концепцію предметів. Тому я рекомендую подивитися, чи це так Enumerable
. Це також гарантує існування#count
.
Наприклад,
[1,2,3].is_a? Enumerable
[1,2,3].count
відзначити , що, в той час як size
, length
і count
всі роботи для масивів, count
це правильний сенс тут - (наприклад, 'abc'.length
і 'abc'.size
обидва працюють, але'abc'.count
не працює , як це).
Застереження: рядок is_a? Численні, тому, можливо, це не те, чого ви хочете ... залежить від вашої концепції об'єкта, подібного до масиву.
Спробуйте:
def is_array(a)
a.class == Array
end
EDIT : Інша відповідь набагато краща за мою.
Також розглянути можливість використання Array()
. З посібника зі стилю Ruby Community :
Використовуйте Array () замість явної перевірки масиву або [* var] при роботі зі змінною, яку ви хочете розглядати як масив, але ви не впевнені, що це масив.
# 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]]