Juan
Juan

Reputation: 2103

Group by week in the first column of an array ruby

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

Answers (2)

Cary Swoveland
Cary Swoveland

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

Aleksei Matiushkin
Aleksei Matiushkin

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

Related Questions