Ruby: Best way to parse a conditional array element
I'm doing API calls that will conditionally return a couple differ开发者_StackOverflow中文版ent elements. My code is currently:
if array['productId']
value = array['productId'][0]
end
I feel like there is a more succinct way of doing this. Some Ruby magic.
A better way :
value = array['productId'][0] if array['productId']
However, array['productId'][0] is not ruby natural. What does your array consist of ?
Since Ruby 2.3.0, the shortest way is Array#dig
:
array.dig('productId', 0)
http://ruby-doc.org/core-2.3.0_preview1/Array.html#method-i-dig
I am not sure if you are using value
just temporarily or actually using it later, and what you want to do with value
when the condition is not met. If you want to return nil
for missing keys, then
array['productId'].to_a[0]
can work. Otherwise, SpyrosP's answer will be the best.
This might be a bit pedantic, but to make sure it works in all circumstances, you should not check 'not-nil', but rather that it is indexable; something like this:
value = array['productId'][0] if array['productId'].is_a? Array
Or even better:
value = array['productId'][0] if array['productId'].respond_to? '[]'
Otherwise your code will fail if array['productId'] == 2
(which on the other hand seems reasonable, given the key used - I would have gone product_ids
instead).
You could use a ternary:
value = array['productId'].nil? ? nil : array['productId'][0]
Your code pattern looks OK; it's possible to be slightly shorter...
value = (t = x['productId']) && t[0]
Using the maybe pattern of Ick, terse and explicit:
value = array['productId'].maybe[0]
While I think your code is fine (although I'd prefer SpyrosP's one-line version), you have some possibilities:
Rails has Object#try, which would let you do either
array['productId'].try(:[], 0)
orarray['productId'].try(:at, 0)
.Some people like the andand gem, which defines
Object#andand
and is used likearray['productId'].andand[0]
.
Ha, I love all the options here. But since I didn't see what I use most, I'll add one more!
value = array['productId'] && array['productId'].first
(I prefer .first
to [0]
because it reads a little better)
This presumes you'll have an array in array['productId']
, which is the right way to do it (rather than type-checking).
Otherwise, the biggest diference between this and your original code, is that this results in value
having nil
assigned to it if the array doesn't have anything, whereas your original results in value
not being defined (which may cause errors, depending on how you use it down the road).
Hope that helps!
精彩评论