Dty
Dty

Reputation: 12273

add or insert to array inside a hash

I have hash named data with a key named checks which is an array of dates. If the key exists I want to append to the existing array. If the key does not exist I need to add an array with the current date. Is there an elegant way to do this in ruby?

This is how I'm doing it right now which seems harder than it should be:

if data.has_key?('checks')
  data['checks'] << DateTime.now
else
  data['checks'] = Array.wrap(DateTime.now)
end

Upvotes: 1

Views: 4095

Answers (6)

etdev
etdev

Reputation: 534

I'm not sure if it's elegant or not, but you could do:

data['checks'] = [*data['checks']] << DateTime.now

Basically if data['checks'] is nil the splat reduces it to [] but if it has entries it reduces to an array with those same entries.

EDIT Here's another option no one else has mentioned:

data['checks'] = (data['checks'] || []) << DateTime.now

EDIT2 Without using the (potentially confusing) splat operator:

data['checks'] = Array(data['checks']) << DateTime.now

Upvotes: 2

tadman
tadman

Reputation: 211560

Normally I'd attack it like this:

checks = data['checks'] ||= [ ]
checks << DateTime.now

If your data hash will only ever have array-like values, do this:

data = Hash.new { |h,k| h[k] = [ ] }

Then you don't need to bother with the ||= thing since assignment will happen automatically.

Upvotes: 5

Jack Noble
Jack Noble

Reputation: 2098

data['checks'] = data.fetch('checks', []) << DateTime.now

Hash#fetch takes a key and a value to return if the key is missing. Perhaps a little more elegant than splatting into an array literal.

Upvotes: 2

sa77
sa77

Reputation: 3603

if data[:checks]
  data[:checks] << DateTime.now
else
  data[:checks] = [DateTime.now]
end

one liner

data[:checks] ? data[:checks] << DateTime.now : data[:checks] = [DateTime.now]

Upvotes: 0

Alex Kojin
Alex Kojin

Reputation: 5204

data['checks']= Array.wrap(data['checks']) << DateTime.now

But think more elegant way is this:

data['checks']= Array.wrap(data['checks']) + [DateTime.now]

Array.wrap return a blank array or existing array. Plus operator will merge two arrays and assign new array to data['checks']

Upvotes: 0

Deepak Mahakale
Deepak Mahakale

Reputation: 23661

if data.key?('checks')
  data['checks'] << DateTime.now
else 
  data['checks'] = [DateTime.now]
end

Upvotes: 0

Related Questions