2

I've got a variable I'd like to use as a key to a hash that contains its own key and array.

e.g.

custArray = Array.new
custArray << {"c1001" => {"purchases" => ["prod01"]}}

I want to be able to do something like:

if custArray[:c1001].exists?
  custArray[{:c1001["purchases"]} << "prod02"]
end

but I'm just totally stuck.

2
  • 4
    Prefer cust_array over custArray in Ruby. Also, "c1001" and :c1001 are not equivalent hash keys. Commented May 7, 2018 at 15:11
  • 1
    I suggest that in future you not be in such a rush to select an answer. There's no hurry. Commented May 7, 2018 at 18:02

5 Answers 5

3

You can resolve it with:

if c = custArray.find { |h| h.key? 'c1001' }
  c.dig('c1001', 'purchases') << "prod2"
end

Or if you can have more than one result with this key:

custArray.select { |h| h.key? 'c1001' }.each do |c|
  c.dig('c1001', 'purchases') << "prod2"
end
Sign up to request clarification or add additional context in comments.

Comments

2

If you only want to update the first instance of the array you can do:

target = custArray.find { |hash| hash.key? 'c1001' }
target['c1001']['purchases'] << 'prod02' if target

If you want to update all instances of the array you can do (backslashes are for console purposes only):

custArray \
  .select { |hash| hash.key? 'c1001' } \
  .each { |hash| hash['c1001']['purchases'] << 'prod02' }

Comments

2

You can use select from the array of hashes to see if the key is there:

target = custArray.find { |h| h.key? 'c1001' }
target['c1001']['purchases'] <<  "prod02" unless target.nil?

Or if array contains multiple hashes with the same key:

custArray.select { |h| h.key? 'c1001' }.each do |h|
  h['c1001']['purchases'] <<  "prod02" 
end

3 Comments

Apologies, I edited the question. That absolutely worked.
I edited my answer as the first answer I gave was incorrect
See last update. But also be aware, an array may contain multiple hashes that have the same keys. So make sure however you're building your array, those keys are unique. Also prefer snake case in ruby cust_array vs custArray.
1

Also, you can write something similar to code that you already provide

custArray.each do |h|
  h['c1001']['purchases'] << 'prod02' if h.keys.include?('c1001')
end

That allows reducing the count of iteration loops

1 Comment

This solution will also handle if you have duplicate array values with the same hash key c1001
0
custArray.find { |h| h.key?('c1001') }&.dig('c1001', 'purchases')&.push("prod02")
  #=> ["prod01", "prod02"]
custArray
  #=> [{"c1001"=>{"purchases"=>["prod01", "prod02"]}}]

custArray.find { |h| h.key?('c1002') }&.dig('c1002', 'purchases')&.push("prod02")
  #=> nil
custArray
  #=> [{"c1001"=>{"purchases"=>["prod01"]}}]

custArray.find { |h| h.key?('c1001') }&.dig('c1001', 'popsicles')&.push("prod02")
  #=> nil
custArray
  #=> [{"c1001"=>{"purchases"=>["prod01"]}}]

& is Ruby's Safe Navigation Operator. See also Hash#dig. Both made their debut in Ruby v2.3.

Comments

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.