1

I have a hash of an array of arrays. The array is indexed by the hash (that is the way I am reading this):

[
 {"name":"G18","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]},
 {"name":"G19","data": [["M16",141],["M203",57],["M29S",142]]},
 {"name":"G20","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]}
]

I want to select the hashes that contain the array G18, and return only the data.

I tried searching for answer, but I haven't found anything like this yet.

2
  • Please edit to state whether the number of hashes h for which h.key("name") #=> true and h["name"] === "Gi8" #=> true can be zero or more than one. Commented Feb 14, 2018 at 22:00
  • 1
    Note "G18" is not an array and you presumably mean that you want to return the value of :data. If you assign a variable to your array (arr = [{...) you could say that you "wish to return h[:data] for the element of h of arr for which h[:name] == "G18"is true. That assumes there is exactly one such hash h having that property. If zero or more than one could have that property, the statement would have to be adjusted according. Commented Feb 14, 2018 at 22:39

3 Answers 3

3

This will work for you if you have only one item with name "G18":

a.find {|e| e[:name] == "G18" }[:data]

See: Enumerable#find in the official docs.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, that solved my problem, greatly appreciated.
a.find {|e| e[:name] == "G17" }[:data] raises an exception because a.find {|e| e[:name] == "G17" } #=> nil and there is no method NilClass#[]. You could use Ruby's Safe Navigation operator to deal with this case: a.find {|e| e[:name] == "G17" }&.[](:data) #=> nil. Note that you cannot write a.find {|e| e[:name] == "G17" }&.[:data].
@CarySwoveland , blame me not -)) just tell those mad pythonistas that they need basic arithmetics, not decimal handling libraries, string representations, logarithms etc -))
3

Given:

ary = [
  {"name":"G18","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]},
  {"name":"G19","data": [["M16",141],["M203",57],["M29S",142]]},
  {"name":"G20","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]}
]

Try:

ary.select{|hsh| hsh[:name] == 'G18'}.first[:data]
 => [["X301", 141], ["x7901", 57], ["x2100", 142], ["x90", 58]] 

In fact, marmeladze's answer is the correct one:

ary.find{|hsh| hsh[:name] == 'G18'}[:data]

Using select was a misfire.

Comments

2
collection = [
  {"name":"G18","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]},
  {"name":"G19","data": [["M16",141],["M203",57],["M29S",142]]},
  {"name":"G20","data": [["X301",141],["x7901",57],["x2100",142],["x90",58]]}
]

def data_for_name(name, collection)
  collection.find { |item| item[:name] == name }[:data]
end

p data_for_name("G18", collection)

4 Comments

How does this differ from @marmeladze's earlier answer?
It's always a good idea in Ruby to extract logic such as this into methods. In this case, doing so allows this code to work with any collection of hashes that have name and data keys. Also lets us defer until runtime the decision as to what item we're looking for.
I think what you said is obvious and could be applied equally to any SO answer that has not been wrapped in the obvious method.
@CarySwoveland -- As someone who teachers beginners how to code, this is certainly not obvious.

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.