1

I'm parsing JSON from an API. I have a foo element that's a hash sometimes, and an array of hashes, other times.

foo: { ... }

foo: [
  { ... },
  { ... }
]

I'd like to just use Array(foo) to always get the an array with at least the one element, but it converts the hash to [[..., ...], [..., ...]]. Is there an elegant way to handle this, besides using foo.is_a?(Hash/Array)?

2
  • 1
    Considering that you do not have a Rails tag, why would you want to load something as massive as ActiveSupport to perform a simple calculation? There's nothing simpler than the way @Veet does it. Even if the lack of a Rails tag was an oversight, you cannot very well add it now. Commented Dec 8, 2015 at 18:47
  • @CarySwoveland correct. This is in a gem, so ruby only. Thanks! Commented Dec 9, 2015 at 3:09

3 Answers 3

3

Adding to @yez answer, if you are not using activesupport, you can extend Array to have a wrap function:

def Array.wrap(object)
  if object.nil?
    []
  elsif object.respond_to?(:to_ary)
    object.to_ary || [object]
  else
    [object]
  end
end

Copied from http://apidock.com/rails/Array/wrap/class

Another crude way to implement it is:

def Array.wrap(object)
  return [] if object.nil?
  [object].flatten(1)
end
Sign up to request clarification or add additional context in comments.

2 Comments

You should use flatten(1) to avoid flattening nested arrays.
Yes, but the question has no Rails tag, so a pure-Ruby solution solution is of principle interest.
3

In a Rails environment, with access to activesupport:

You could use Array.wrap

foo = { a: :b }
=> {:a=>:b}
Array.wrap(foo)
=> [{:a=>:b}]
Array.wrap([1,2,3])
=> [1, 2, 3]

Without Rails, you could do gem install activesupport and then in your code: require 'activesupport'

1 Comment

gem install activesupport; require activesupport
2

If you want to solve it using plain Ruby then you can push the item(s) (either Array of Hashes or Hash) to an empty array and then flatten the array like following:

2.0.0-p247 :001 > [{a:1}].flatten(1)
 => [{:a=>1}] 
2.0.0-p247 :002 > [[{a:1},{b:2}]].flatten(1)
 => [{:a=>1}, {:b=>2}]

i.e. [foo].flatten(1) should work.

5 Comments

You don't need push, just: [{a:1}].flatten / [[{a:1},{b:2}]].flatten
Thanks Stefan for your input. The answer above should suffice what Dudo is asking for without even using active support. i.e. he gets the foo element as a hash or as an array of hashes and he wants to convert it to an array of hash or an array of hashes.
I just wanted to point out that [].push(obj) is equivalent to [obj]
Got your point. [foo].flatten should work. Edited the answer.
This is the best answer, imo, short and sweet and pure-Ruby, as called for by the question. You could also write [*[obj]]; e.g., [*[{a:1}]] #=> [{:a=>1}], [*[{a:1, b:2}]] #=> [{:a=>1, :b=>2}].

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.