Reputation: 2103
I have the next bidimensional array, where the first componente belongs to ActiveSupport::TimeWithZone and the second component is a string
[[Sun, 16 Jul 2017 14:41:56 -03 -03:00, "open"],
[Sun, 16 Jul 2017 14:41:56 -03 -03:00, "closed"],
[Sun, 16 Jul 2017 14:41:56 -03 -03:00, "closed"],
[Mon, 10 Jul 2017 00:00:00 -03 -03:00, "open"],
[Sun, 16 Jul 2017 14:45:31 -03 -03:00, "closed"],
[Sun, 16 Jul 2017 14:44:41 -03 -03:00, "open"],
[Sun, 16 Jul 2017 14:44:39 -03 -03:00, "closed"],
[Sun, 16 Jul 2017 14:44:13 -03 -03:00, "open"],
[Mon, 10 Jul 2017 00:00:00 -03 -03:00, "closed"],
[Fri, 14 Jul 2017 00:00:00 -03 -03:00, "open"],
[Mon, 17 Jul 2017 00:00:00 -03 -03:00, "open"]]
I need to convert that array in efficient way into
{["09-Jul", "open"]=>2, ["16-Jul", "open"]=>1, ["09-Jul", "closed"]=>0, ["16-Jul", "closed"]=>1}
That is, I need to convert the first component into the format %b-%d. Also, I need group by week and "status". Finally I need to count these grouped values and present the data with hash format as the second example
Upvotes: 0
Views: 137
Reputation: 110685
You could create the desired hash with the form of Hash::new that takes an argument equal to the default value of the hash, which here we want to be zero. What that means is that if a hash h
, defined h = Hash.new(0)
, does not have a key k
, then h[k]
returns the default value (here 0
), without modifying the hash h
.
input.each_with_object(Hash.new(0)) { |(d,v),h| h[[d.strftime('%b-%d'), v]] += 1
Upvotes: 0
Reputation: 121000
input.group_by { |d, v| [d.strftime('%b-%d'), v] }
.map { |k, v| [k, v.count] }.to_h
Also, for Ruby 2.4+ it could be simplified (credits go to @MarkThomas) to:
input.group_by { |d, v| [d.strftime('%b-%d'), v] }
.transform_values(&:count)
Upvotes: 2