user984621
user984621

Reputation: 48443

Ruby - how to add a conditional key to a hash?

I have this method creating a hash:

def build_values(data)
  {
    key1: data.k1,
    key2: data.k2,
    key3: (@var == true ? data.k3 : nil),
    key4: data.k4,
    ...
  }
end

If @var == true, then key3 has the value data.k2. That's good.

If it is not true, then key3 has not value (actually, it has nil). But ideally, I would not want to print the key3 at all.

How do I do that? Something like this doesn't work:

def build_values(data)
  {
    key1: data.k1,
    key2: data.k2,
    if @var == true
      key3: data.k3
    end,
    key4: data.k4,
    ...
  }
end

Upvotes: 2

Views: 1699

Answers (4)

Chiara Ani
Chiara Ani

Reputation: 1083

def build_values(data)
  hash = {
    key1: data.k1,
    key2: data.k2,
    key4: data.k4,
    ...
  }
  hash[:key3] = data.k3 if @var == true  
end

Upvotes: 1

Stefan
Stefan

Reputation: 114138

Not the prettiest solution, but ** could be used:

{
  key1: data.k1,
  key2: data.k2,
  **(@var == true ? { key3: data.k3 } : {}),
  key4: data.k4,
}

Note that == true can be omitted if you just care whether @var is truthy.

Upvotes: 6

iGian
iGian

Reputation: 11183

Maybe you can consider something like rejecting the key if not @var:

def build_values(data)
  {
    key1: data.k1,
    key2: data.k2,
    key3: data.k3,
    key4: data.k4
    }.reject{ |k, _| k == :key3 && !@var }
end

Upvotes: 1

BroiSatse
BroiSatse

Reputation: 44675

If you care for the order of keys, you can do:

def build_values(data)
  data = {
    key1: data.k1,
    key2: data.k2
  }
  data[:key3] = data.k3 if @var == true
  data.merge(
    key4: data.k4,
    ...
  }
end

Alternatively, you can use predefined key order (this could be hand when there are more optional keys):

KEY_ORDER = %i[key1 key2 key3 key4 ...]

def build_values(data)
  data = {
    key1: data.k1,
    key2: data.k2,
    key4: data.k4
  }
  data[:key3] = data.k3 if @var == true
  data.sort_by { |k, _| KEY_ORDER.index(k) }.to_h 
end

However, if you got here it might be worth considering a custom class - either Struct or even Hash subclass to deal with this data.

Upvotes: 1

Related Questions