What Is an Elegant Way in Ruby to Tell If a Variable Is a Hash or an Array

What is an elegant way in Ruby to tell if a variable is a Hash or an Array?

You can just do:

@some_var.class == Hash

or also something like:

@some_var.is_a?(Hash)

It's worth noting that the "is_a?" method is true if the class is anywhere in the objects ancestry tree. for instance:

@some_var.is_a?(Object)  # => true

the above is true if @some_var is an instance of a hash or other class that stems from Object. So, if you want a strict match on the class type, using the == or instance_of? method is probably what you're looking for.

Is there an elegant way to iterate through an array and stop before the end?

What you are effectively doing is, first mapping the elements of the Array with a transformation, and then finding the first transformed element that satisfies some predicate.

We can express this like this (I'm re-using the definitions from @iGian's answer, but with an added side-effect so that you can observe the evaluation of the transformation operation):

def complex_stuff_with(e)
p "#{__callee__}(#{e.inspect})"
e**2
end

ary = [1, 2, 3, 2]
x_i_want = 4

ary
.map(&method(:complex_stuff_with))
.find(&x_i_want.method(:==))
# "complex_stuff_with(1)"
# "complex_stuff_with(2)"
# "complex_stuff_with(3)"
# "complex_stuff_with(2)"
#=> 4

This gives us the correct result but not the correct side-effects. You want the operation to be lazy. Well, that's easy, we just need to convert the Array to a lazy enumerator first:

ary
.lazy
.map(&method(:complex_stuff_with))
.find(&x_i_want.method(:==))
# "complex_stuff_with(1)"
# "complex_stuff_with(2)"
#=> 4

Or, using the definitions from your question:

array
.lazy
.map(&method(:complex_stuff_with))
.find(&:is_the_one_i_want?)

How to determine if the contents of a text field are a hash or a string in rails using ruby?

You could

if suggestion.kind_of?(Hash)
# ...
end

or

if Hash === suggestion
# ...
end

Is there a more elegant way of writing a while loop in Ruby where the array size is not known?

Assuming your goal is to create an array of odd numbers up to a limit, you can use a range with a step.

limit = 20 
array = (1..limit).step(2).to_a

EDIT

If you want to be able to descend as well as ascend you can use step.

#Ascending 
start = 1
limit = 20

array = start.step(limit, 2).to_a

#Descending
start = 20
limit = 1

array = start.step(limit, -2).to_a

Ruby - elegantly convert variable to an array if not an array already

[*foo] or Array(foo) will work most of the time, but for some cases like a hash, it messes it up.

Array([1, 2, 3])    # => [1, 2, 3]
Array(1) # => [1]
Array(nil) # => []
Array({a: 1, b: 2}) # => [[:a, 1], [:b, 2]]

[*[1, 2, 3]] # => [1, 2, 3]
[*1] # => [1]
[*nil] # => []
[*{a: 1, b: 2}] # => [[:a, 1], [:b, 2]]

The only way I can think of that works even for a hash is to define a method.

class Object; def ensure_array; [self] end end
class Array; def ensure_array; to_a end end
class NilClass; def ensure_array; to_a end end

[1, 2, 3].ensure_array # => [1, 2, 3]
1.ensure_array # => [1]
nil.ensure_array # => []
{a: 1, b: 2}.ensure_array # => [{a: 1, b: 2}]

Should multiple array/hash lookups be stored in a variable

So I was wondering if multiple array or hash lookups are so expensive

Expensive calls are not the only reason for not doing the call multiple times. It also clutters the code without real need. Consider this not-so-contrived example:

Order.new(
name: params[:order][:name],
total: params[:order][:total],
line_items: [
{
product_name: params[:order][:line_item][:product],
price: params[:order][:line_item][:price],
}
]
)

Even though those hash accesses are super-cheap, it still makes sense to extract them, for readability reasons.

order_params     = params[:order]
line_item_params = order_params[:line_item]

Order.new(
name: order_params[:name],
total: order_params[:total],
line_items: [
{
product_name: line_item_params[:product],
price: line_item_params[:price],
}
]
)


Related Topics



Leave a reply



Submit