Roberto Pezzali
Roberto Pezzali

Reputation: 2504

Ruby, how to reduce an array of dates in string format keeping only month and array index

I need to draw a chart and on the X axis I have dates... I have an array like this...

data = ["2020-02-15",
 "2020-02-16",
 "2020-02-17",
 "2020-02-18",
 "2020-02-19",
 "2020-02-20",
 "2020-02-21",
 "2020-02-22",
 "2020-02-23",
 "2020-02-24",
 "2020-02-25",
 "2020-02-26",
 "2020-02-27",
 "2020-02-28",
 "2020-02-29" ... ]

The array has about 500 elements... I cannot draw 500 labels, I just need the month.

My label has this format

g.labels = {0 => '2003', 2 => '2004', 4 => '2005', 6 => '2006'}

The key is the index, the value is the month.

So I use

x = Hash[(0...data.size).zip data]

And the result is

{0=>"2020-02-15",
 1=>"2020-02-16",
 2=>"2020-02-17",
 3=>"2020-02-18",
 4=>"2020-02-19",
 5=>"2020-02-20"}

Now I have to keep just the month. Because the first value is "2020-02-15" I start with february 15th, then I have to keep march 15th, etc...

The result must be

{0=>"February",
 30=>"March",
 61=>"April"...}

How can I do?

Upvotes: 0

Views: 130

Answers (2)

Zain Arshad
Zain Arshad

Reputation: 1907

You can use this:

data = {0=>"2020-02-15",
    1=>"2020-02-16",
    2=>"2020-03-17",
    3=>"2020-04-18",
    4=>"2020-05-19",
    5=>"2020-09-20",
    6=>"2020-04-15",
    7=>"2020-04-20",
    8=>"2020-06-15",
    9=>"2020-09-15"}
match_date = Date.parse(data.first.last).day
months = data.map{|k, v| [k, Date.parse(v).strftime("%B")] if Date.parse(v).day == match_date}.compact.to_h

Output:

{0=>"February", 6=>"April", 8=>"June", 9=>"September"}
 

Upvotes: 0

anquegi
anquegi

Reputation: 11532

You can work with regexp or just use the Date class:

[8] pry(main)> h
=> {0=>"2020-02-15", 1=>"2020-02-16", 2=>"2020-02-17", 3=>"2020-02-18", 4=>"2020-02-19", 5=>"2020-02-20"}
[10] pry(main)> h.each do |k,v|
[10] pry(main)*   puts "date #{k} month number is #{Date.parse(v).month}"
[10] pry(main)* end
date 0 month number is 2
date 1 month number is 2
date 2 month number is 2
date 3 month number is 2
date 4 month number is 2
date 5 month number is 2

or by name:

[11] pry(main)> h.each do |k,v|
[11] pry(main)*   puts "date #{k} month number is #{Date.parse(v).strftime("%B")}"
[11] pry(main)* end
date 0 month number is February
date 1 month number is February
date 2 month number is February
date 3 month number is February
date 4 month number is February
date 5 month number is February

Since you want to use array tou do not need to use has notation:

[18] pry(main)> h.values
=> ["2020-02-15", "2020-02-16", "2020-02-17", "2020-02-18", "2020-02-19", "2020-02-20"]
[19] pry(main)> h.values.map { |d| Date.parse(d).month }
=> [2, 2, 2, 2, 2, 2]

or you can map over a hash and modify the hash itself:

[20] pry(main)> h
=> {0=>"2020-02-15", 1=>"2020-02-16", 2=>"2020-02-17", 3=>"2020-02-18", 4=>"2020-02-19", 5=>"2020-02-20"}
[21] pry(main)> h.update(h){ |_,d| Date.parse(d).month }
=> {0=>2, 1=>2, 2=>2, 3=>2, 4=>2, 5=>2}
[22] pry(main)> h
=> {0=>2, 1=>2, 2=>2, 3=>2, 4=>2, 5=>2}

[24] pry(main)> h.transform_values! { |v| Date.parse(v).month }
=> {0=>2, 1=>2, 2=>2, 3=>2, 4=>2, 5=>2}

but I recoomend to create a new hash

[26] pry(main)> h.transform_values { |v| Date.parse(v).month }
=> {0=>2, 1=>2, 2=>2, 3=>2, 4=>2, 5=>2}
[27] pry(main)> h
=> {0=>"2020-02-15", 1=>"2020-02-16", 2=>"2020-02-17", 3=>"2020-02-18", 4=>"2020-02-19", 5=>"2020-02-20"}

finally for your result:

[28] pry(main)> h.transform_values { |v| Date.parse(v).strftime("%B") }
=> {0=>"February", 1=>"February", 2=>"February", 3=>"February", 4=>"February", 5=>"February"}

you can also filter values on a hash:

[29] pry(main)> h.select { |k,v| Date.parse(v).day == 15 }.transform_values { |v| Date.parse(v).strftime("%B") }
=> {0=>"February"}

Upvotes: 1

Related Questions