1

Example as follows:

if house['windows'][floor_1]
  house['windows'][floor_1] << north_side
else
  house['windows'][floor_1] = [north_side]
end

Best way to check for existing key?

sawa
  • 165,429
  • 45
  • 277
  • 381
JohnSmith
  • 1,078
  • 1
  • 10
  • 21
  • Possible duplicate of [Creating a Hash with values as arrays and default value as empty array](https://stackoverflow.com/questions/30367487/creating-a-hash-with-values-as-arrays-and-default-value-as-empty-array) – user513951 Feb 16 '19 at 15:31
  • One common way of doing this (which some claim is faster than using a default proc): `h = {}; h[:a] = (h[:a] || []) << 1 #=> [1]; h[:a] = (h[:a] || []) << 2 #=> [1, 2]`. – Cary Swoveland Feb 16 '19 at 18:46
  • What is `house`? – sawa Feb 19 '19 at 10:03

3 Answers3

4

The fact that house['windows'] is an element in a hash already is a bit of a red herring, so I will use windows as a variable referencing a hash.

Set up a default value for the windows hash, so that any non-preexisting key is assigned an array value:

windows = Hash.new {|hash, key| hash[key] = [] }

Now you can append (<<) to new hash elements automatically.

windows['floor_1'] << 'north_side'

windows # => {"floor_1"=>["north_side"]}

For your specific case, replace windows with house['windows'].


EDIT

As pointed out in the comments, this behavior can be added to an already-instantiated hash:

windows.default_proc = proc {|hash, key| hash[key] = [] }
user513951
  • 12,445
  • 7
  • 65
  • 82
  • 1
    What to do if `windows` is external data and we can't create it? – mechnicov Feb 16 '19 at 16:02
  • 1
    @mechnicov Then you can set the default proc with [`#default_proc`](https://ruby-doc.org/core-2.6.1/Hash.html#method-i-default_proc-3D). `windows.default_proc = proc { |hash, key| hash[key] = [] }` – 3limin4t0r Feb 16 '19 at 16:12
  • @JohanWentholt, good idea. I asked this question so that user513951 improves the answer. – mechnicov Feb 16 '19 at 16:18
2

I would do something like:

house['windows'][floor_1] ||= []
house['windows'][floor_1] << north_side
arieljuod
  • 15,460
  • 2
  • 25
  • 36
1

Given your Hash, I imagine:

house = { windows: { floor_0: ['f0'] } }

You can check the existence of a key using Hash#has_key?

house[:windows].has_key? :floor_1 #=> false

So you can create it:

house[:windows].merge!({floor_1: []}) unless house[:windows].has_key? :floor_1


Better if you define a defalt value using for example Hash#default_proc=:
house[:windows].default_proc = proc { |h, k| h[k] = [] } 

So you can

house[:windows][:floor_3] << 'f3'

house #=> {:windows=>{:floor_0=>["f0"], :floor_1=>[], :floor_3=>["f3"]}}
iGian
  • 11,023
  • 3
  • 21
  • 36