Fill gaps in Array of Hashes

J

Joao Silva

I have the following object as a result from MySQL:

[{:positive=>"0", :neutral=>"2", :total=>"5", :date=>"2009-12-01",
:negative=>"3"}, {:positive=>"3", :neutral=>"3", :total=>"7",
:date=>"2009-12-08", :negative=>"1"}, {:positive=>"1", :neutral=>"1",
:total=>"3", :date=>"2009-12-09", :negative=>"1"}]

I want to fill gaps (for example from 2009-11-19 till 2010-10-01) with
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>"HEREDATE",
:negative=>"1" - how i can do this in ruby? In MySQL it's impossible to
do :-(.
 
A

Aldric Giacomoni

Joao said:
I have the following object as a result from MySQL:

[{:positive=>"0", :neutral=>"2", :total=>"5", :date=>"2009-12-01",
:negative=>"3"}, {:positive=>"3", :neutral=>"3", :total=>"7",
:date=>"2009-12-08", :negative=>"1"}, {:positive=>"1", :neutral=>"1",
:total=>"3", :date=>"2009-12-09", :negative=>"1"}]

I want to fill gaps (for example from 2009-11-19 till 2010-10-01) with
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>"HEREDATE",
:negative=>"1" - how i can do this in ruby? In MySQL it's impossible to
do :-(.

Well, the dumb, brute-force way to do it would be something like this, I
guess:

# Assuming your array is called 'array'
require 'rubygems'
require 'activesupport' # What? I'm lazy. to_date is damn handy.

("2009-11-19".to_date.."2010-10-01".to_date).each do |date|
exists = array.find { |x| x[:date] == date.to_s }
next if exists # If the date is found in the array, next date please.
array << { :positive => "0", :neutral => "0", :total => "0", :date =>
date,
:negative => "1" }
end

Do you understand this code?
 
J

Joao Silva

Yep, i understand, but it returns wrong value (and not sorted by date
;-():

("2009-11-11".to_date.."2010-01-01".to_date).each do |date|
exists = result.find { |x| x[:date] == date.to_s }
next if exists
result << { :positive => "0", :neutral => "0", :total => "0",
:date => date, :negative => "0" }
end

return result

=> [{:positive=>"0", :neutral=>"2", :total=>"5", :date=>"2009-12-01",
:negative=>"3"}, {:positive=>"3", :neutral=>"3", :total=>"7",
:date=>"2009-12-08", :negative=>"1"}, {:positive=>"1", :neutral=>"1",
:total=>"3", :date=>"2009-12-09", :negative=>"1"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Wed, 11 Nov 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Thu, 12 Nov 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Fri, 13 Nov 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Sat, 14 Nov 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Sun, 15 Nov 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Mon, 16 Nov 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Tue, 17 Nov 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Wed, 18 Nov 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Thu, 19 Nov 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Fri, 20 Nov 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Sat, 21 Nov 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Sun, 22 Nov 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Mon, 23 Nov 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Tue, 24 Nov 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Wed, 25 Nov 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Thu, 26 Nov 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Fri, 27 Nov 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Sat, 28 Nov 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Sun, 29 Nov 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Mon, 30 Nov 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Tue, 01 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Wed, 02 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Thu, 03 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Fri, 04 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Sat, 05 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Sun, 06 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Mon, 07 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Tue, 08 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Wed, 09 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Thu, 10 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Fri, 11 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Sat, 12 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Sun, 13 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Mon, 14 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Tue, 15 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Wed, 16 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Thu, 17 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Fri, 18 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Sat, 19 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Sun, 20 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Mon, 21 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Tue, 22 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Wed, 23 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Thu, 24 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Fri, 25 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Sat, 26 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Sun, 27 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Mon, 28 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Tue, 29 Dec 2009, :negative=>"0"},
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>Wed, 30 Dec 2009,
:negative=>"0"}, {:positive=>"0", :neutral=>"0", :total=>"0",
:date=>Thu, 31 Dec 2009, :negative=>"0"}, {:positive=>"0",
:neutral=>"0", :total=>"0", :date=>Fri, 01 Jan 2010, :negative=>"0"}]
 
A

Aldric Giacomoni

Joao said:
Yep, i understand, but it returns wrong value (and not sorted by date
;-():

Try this then.

("2009-11-11".to_date.."2010-01-01".to_date).each do |date|
exists = result.find { |x| x[:date] == date.to_s }
next if exists
result << { :positive => "0", :neutral => "0", :total => "0",
:date => date.to_s, :negative => "0" }
end
array.sort! { |a, b| a[:date].to_date <=> b[:date].to_date }

Just a teeny tiny little "to_s".
And sorting an array is a simple matter of looking up the sort method in
the rdoc (which IS your best friend).
 
A

Aldric Giacomoni

Joao said:
I have the following object as a result from MySQL:

[{:positive=>"0", :neutral=>"2", :total=>"5", :date=>"2009-12-01",
:negative=>"3"}, {:positive=>"3", :neutral=>"3", :total=>"7",
:date=>"2009-12-08", :negative=>"1"}, {:positive=>"1", :neutral=>"1",
:total=>"3", :date=>"2009-12-09", :negative=>"1"}]

I want to fill gaps (for example from 2009-11-19 till 2010-10-01) with
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>"HEREDATE",
:negative=>"1" - how i can do this in ruby? In MySQL it's impossible to
do :-(.

Alright... Now that I've helped you do what you asked for, please tell
us what you actually want to do, because actually filling up a hash with
default data is really not optimal.
 
R

Robert Klemme

2009/12/10 Aldric Giacomoni said:
Joao said:
I have the following object as a result from MySQL:

[{:positive=3D>"0", :neutral=3D>"2", :total=3D>"5", :date=3D>"2009-12-01= ",
:negative=3D>"3"}, {:positive=3D>"3", :neutral=3D>"3", :total=3D>"7",
:date=3D>"2009-12-08", :negative=3D>"1"}, {:positive=3D>"1", :neutral=3D= "1",
:total=3D>"3", :date=3D>"2009-12-09", :negative=3D>"1"}]

I want to fill gaps (for example from 2009-11-19 till 2010-10-01) with
{:positive=3D>"0", :neutral=3D>"0", :total=3D>"0", :date=3D>"HEREDATE",
:negative=3D>"1" - how i can do this in ruby? In MySQL it's impossible t= o
do :-(.

Well, the dumb, brute-force way to do it would be something like this, I
guess:

# Assuming your array is called 'array'
require 'rubygems'
require 'activesupport' # What? I'm lazy. to_date is damn handy.

("2009-11-19".to_date.."2010-10-01".to_date).each do |date|
=A0exists =3D array.find { |x| x[:date] =3D=3D date.to_s }
=A0next if exists # If the date is found in the array, next date please.
=A0array << { :positive =3D> "0", :neutral =3D> "0", :total =3D> "0", :da= te =3D>
date,
=A0 =A0 =A0 =A0 =A0 =A0 :negative =3D> "1" }
end

Here's a different approach - not with dates though.

# just an example
def next_val(x)
x + 2
end

with_gaps =3D Array.new(10) { rand(40) * 2 }

puts "before"
p with_gaps

with_gaps.sort.each_cons 2 do |a,b|
next if a =3D=3D b
x =3D a

while (x =3D next_val(x)) !=3D b
with_gaps << x
end
end

puts "after"
p with_gaps.sort

# automated check
with_gaps.sort.each_cons 2 do |a,b|
raise("Wrong distance %s" % [a,b].inspect) unless a =3D=3D b || next_val(=
a) =3D=3D b
end

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

Joao Silva

Aldric said:
Joao said:
I have the following object as a result from MySQL:

[{:positive=>"0", :neutral=>"2", :total=>"5", :date=>"2009-12-01",
:negative=>"3"}, {:positive=>"3", :neutral=>"3", :total=>"7",
:date=>"2009-12-08", :negative=>"1"}, {:positive=>"1", :neutral=>"1",
:total=>"3", :date=>"2009-12-09", :negative=>"1"}]

I want to fill gaps (for example from 2009-11-19 till 2010-10-01) with
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>"HEREDATE",
:negative=>"1" - how i can do this in ruby? In MySQL it's impossible to
do :-(.

Alright... Now that I've helped you do what you asked for, please tell
us what you actually want to do, because actually filling up a hash with
default data is really not optimal.

I don't have choice: I need data formed like this to generate report
(chart) data. And i need for each day approporiate values.
 
A

Aldric Giacomoni

Joao said:
Aldric said:
Joao said:
I have the following object as a result from MySQL:

[{:positive=>"0", :neutral=>"2", :total=>"5", :date=>"2009-12-01",
:negative=>"3"}, {:positive=>"3", :neutral=>"3", :total=>"7",
:date=>"2009-12-08", :negative=>"1"}, {:positive=>"1", :neutral=>"1",
:total=>"3", :date=>"2009-12-09", :negative=>"1"}]

I want to fill gaps (for example from 2009-11-19 till 2010-10-01) with
{:positive=>"0", :neutral=>"0", :total=>"0", :date=>"HEREDATE",
:negative=>"1" - how i can do this in ruby? In MySQL it's impossible to
do :-(.

Alright... Now that I've helped you do what you asked for, please tell
us what you actually want to do, because actually filling up a hash with
default data is really not optimal.

I don't have choice: I need data formed like this to generate report
(chart) data. And i need for each day approporiate values.

You could check whether the data is in the array, and return the default
that you want if it's not in there.

Pseudo code:

From date1 to date2, do |date|
data = array.find { |x| x[:date] == date }
if data.nil?
data = { your default hash }
end

do_whatever_you_want_with_data_here
end

Why do you have an array of hashes, anyway?
Why not a hash with the dates as keys and the rest of the hash as
values? a hash of hashes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top