Change a data structure

M

Michael Schmarck

Hello!

I've got the following data structure, which I need to change, to
suit further needs:

timing_given = {
  "Performance Test of Item Access using Lists" => [
    {"Plants" => 100, "Customers" => 50, "Total" => 150},
    {"Plants" => 85,  "Customers" => 60, "Total" => 140},
    {"Plants" => 111, "Customers" => 77, "Total" => 188}
  ],
  "Performance Test of Item Access using Advance Item Search" => [
    {"Work List" => 17, "Total" => 42},
{"Work List" => 10, "Total" => 50},
    {"Work List" => 22, "Total" => 99},
{"Work List" => 15, "Total" => 60}
  ]
}

Now I'd like to change that, so that it looks somewhat like this:

timing_wanted = {
 "Performance Test of Item Access using Lists" => {
   "Plants" => [100, 85, 111], "Customers" => [50, 60, 77], "Total" => [150, 140, 188]
 },
 Performance Test of Item Access using Advance Item Search" => {
   "Work List" => [17, 10, 22], "Bookmarks" => [30, 33, 27], "Total" => [42, 50, 99]
 }
}

Let me explain...

I've got a hash called "timing_given", which has, right now, two keys.
These keys have arrays as values. The elements of these arrays are again
hashes.

Now this should be changed to match what's shown in "timing_wanted". Ie.,
create a hash, which has two keys. These keys should have hashes as values
and the values of these hashes should be arrays.

The data represent some timing measurement data. In the example I'm showing,
the Plants, Customers and Total tests have been run 3 times, consecutively.
So, first the Plants test was run, then the Customers test and then the
Total test.

I want to collect all the Plants (etc.pp.) tests in one array. This array
should have as many elements, as there were test runs for the Plants test.
Accordingly for the other tests.

In reality, there are more tests than what I've shown. And as you can see,
there are two test "categories", called "Performance Test of Item Access
using Lists" and "Performance Test of Item Access using Advance Item Search".
In reality, there might be more. Under these categories, there might be
2, 3, 4 or whatever test runs - but the number of test runs for a category
is always constant.

How would I best "mess up" that timing_given data structure, so that it
resembles the timing_wanted structure?

Thanks a lot,
Michael
 
7

7stud --

Michael said:
Hello!

I've got the following data structure, which I need to change, to
suit further needs:

timing_given = {
  "Performance Test of Item Access using Lists" => [
    {"Plants" => 100, "Customers" => 50, "Total" => 150},
    {"Plants" => 85,  "Customers" => 60, "Total" => 140},
    {"Plants" => 111, "Customers" => 77, "Total" => 188}
  ],
  "Performance Test of Item Access using Advance Item Search" => [
    {"Work List" => 17, "Total" => 42},
{"Work List" => 10, "Total" => 50},
    {"Work List" => 22, "Total" => 99},
{"Work List" => 15, "Total" => 60}
  ]
}

Now I'd like to change that, so that it looks somewhat like this:

timing_wanted = {
 "Performance Test of Item Access using Lists" => {
   "Plants" => [100, 85, 111], "Customers" => [50, 60, 77], "Total" =>
[150, 140, 188]
 },
 Performance Test of Item Access using Advance Item Search" => {
   "Work List" => [17, 10, 22], "Bookmarks" => [30, 33, 27], "Total" =>
[42, 50, 99]
 }
}

Let me explain...

I've got a hash called "timing_given", which has, right now, two keys.
These keys have arrays as values. The elements of these arrays are again
hashes.

Now this should be changed to match what's shown in "timing_wanted".
Ie.,
create a hash, which has two keys. These keys should have hashes as
values
and the values of these hashes should be arrays.

The data represent some timing measurement data. In the example I'm
showing,
the Plants, Customers and Total tests have been run 3 times,
consecutively.
So, first the Plants test was run, then the Customers test and then the
Total test.

I want to collect all the Plants (etc.pp.) tests in one array. This
array
should have as many elements, as there were test runs for the Plants
test.
Accordingly for the other tests.

In reality, there are more tests than what I've shown. And as you can
see,
there are two test "categories", called "Performance Test of Item Access
using Lists" and "Performance Test of Item Access using Advance Item
Search".
In reality, there might be more. Under these categories, there might be
2, 3, 4 or whatever test runs - but the number of test runs for a
category
is always constant.

How would I best "mess up" that timing_given data structure, so that it
resembles the timing_wanted structure?

Thanks a lot,
Michael

Try this:

timing_given = {
"Performance Test of Item Access using Lists" => [
{"Plants" => 100, "Customers" => 50, "Total" => 150},
{"Plants" => 85, "Customers" => 60, "Total" => 140},
{"Plants" => 111, "Customers" => 77, "Total" => 188}
],
"Performance Test of Item Access using Advance Item Search" => [
{"Work List" => 17, "Total" => 42},
{"Work List" => 10, "Total" => 50},
{"Work List" => 22, "Total" => 99},
{"Work List" => 15, "Total" => 60}
]
}

timing_wanted = {}

timing_given.each do |key1, value1|
#Make a list be the default lookup value
#for a non-existent hash key:

timing_wanted[key1] = Hash.new do |h, k|
h[k] = []
end

value1.each do |hash|
hash.each do |key2, value2|
timing_wanted[key1][key2] << hash[key2]
end
end
end

p timing_wanted

--output:--
{"Performance Test of Item Access using Advance Item Search"=>{"Work
List"=>[17, 10, 22, 15], "Total"=>[42, 50, 99, 60]}, "Performance Test
of Item Access using Lists"=>{"Plants"=>[100, 85, 111], "Total"=>[150,
140, 188], "Customers"=>[50, 60, 77]}}
 
Y

yermej

Hello!

I've got the following data structure, which I need to change, to
suit further needs:

timing_given = {
"Performance Test of Item Access using Lists" => [
{"Plants" => 100, "Customers" => 50, "Total" => 150},
{"Plants" => 85, "Customers" => 60, "Total" => 140},
{"Plants" => 111, "Customers" => 77, "Total" => 188}
],
"Performance Test of Item Access using Advance Item Search" => [
{"Work List" => 17, "Total" => 42},
{"Work List" => 10, "Total" => 50},
{"Work List" => 22, "Total" => 99},
{"Work List" => 15, "Total" => 60}
]

}

Now I'd like to change that, so that it looks somewhat like this:

timing_wanted = {
"Performance Test of Item Access using Lists" => {
"Plants" => [100, 85, 111], "Customers" => [50, 60, 77], "Total" => [150, 140, 188]
},
Performance Test of Item Access using Advance Item Search" => {
"Work List" => [17, 10, 22], "Bookmarks" => [30, 33, 27], "Total" => [42, 50, 99]
}

}

Let me explain...

I've got a hash called "timing_given", which has, right now, two keys.
These keys have arrays as values. The elements of these arrays are again
hashes.

Now this should be changed to match what's shown in "timing_wanted". Ie.,
create a hash, which has two keys. These keys should have hashes as values
and the values of these hashes should be arrays.

The data represent some timing measurement data. In the example I'm showing,
the Plants, Customers and Total tests have been run 3 times, consecutively.
So, first the Plants test was run, then the Customers test and then the
Total test.

I want to collect all the Plants (etc.pp.) tests in one array. This array
should have as many elements, as there were test runs for the Plants test.
Accordingly for the other tests.

In reality, there are more tests than what I've shown. And as you can see,
there are two test "categories", called "Performance Test of Item Access
using Lists" and "Performance Test of Item Access using Advance Item Search".
In reality, there might be more. Under these categories, there might be
2, 3, 4 or whatever test runs - but the number of test runs for a category
is always constant.

How would I best "mess up" that timing_given data structure, so that it
resembles the timing_wanted structure?

Thanks a lot,
Michael

I'll offer up an inject version (mostly for novelty's sake):
timing_given.each {|k, v| timing_given[k] = v.inject(Hash.new {|h, k|
h[k] = []}) {|acc, h| h.each {|k, v| acc[k] << v}; acc}}
 
M

Michael Schmarck

7stud -- said:
Try this:

Your code works great - but I changed the data structure in the
meantime, as an Array suits my needs better :( Please see
<
Thanks,
Michael
 
M

Michael Schmarck

yermej said:
I'll offer up an inject version (mostly for novelty's sake):
timing_given.each {|k, v| timing_given[k] = v.inject(Hash.new {|h, k|
h[k] = []}) {|acc, h| h.each {|k, v| acc[k] << v}; acc}}

Geez - did you use to code perl code? Because Perl code tends to
be as unreadable and compact as yours :)

It works good, but I guess I've got some reading to do, to actually
understand why it's working ;->

Cheers,

Michael
 
Y

yermej

yermej said:
I'll offer up an inject version (mostly for novelty's sake):
timing_given.each {|k, v| timing_given[k] = v.inject(Hash.new {|h, k|
h[k] = []}) {|acc, h| h.each {|k, v| acc[k] << v}; acc}}

Geez - did you use to code perl code? Because Perl code tends to
be as unreadable and compact as yours :)

Yes, I've used Perl in the past, but my penchant for inject is rooted
in Scheme.
It works good, but I guess I've got some reading to do, to actually
understand why it's working ;->

This might help, though some would say it's better just to avoid
inject entirely:

timing_given.each do |test_type, test_data|
timing_given[test_type] =
test_data.inject(Hash.new {|h, k| h[k] = []}) do |new_hash,
old_hash|
old_hash.each do |data_field, data_value|
new_hash[data_field] << data_value
end
new_hash
end
end
 
7

7stud --

Michael said:
yermej said:
I'll offer up an inject version (mostly for novelty's sake):
timing_given.each {|k, v| timing_given[k] = v.inject(Hash.new {|h, k|
h[k] = []}) {|acc, h| h.each {|k, v| acc[k] << v}; acc}}

Geez - did you use to code perl code? Because Perl code tends to
be as unreadable and compact as yours :)

It works good, but I guess I've got some reading to do, to actually
understand why it's working ;->

Don't bother. inject() is such an inefficient function it should never
be used in ruby code.
 
J

James Gray

Michael said:
yermej said:
I'll offer up an inject version (mostly for novelty's sake):
timing_given.each {|k, v| timing_given[k] = v.inject(Hash.new {|h,
k|
h[k] = []}) {|acc, h| h.each {|k, v| acc[k] << v}; acc}}

Geez - did you use to code perl code? Because Perl code tends to
be as unreadable and compact as yours :)

It works good, but I guess I've got some reading to do, to actually
understand why it's working ;->

Don't bother. inject() is such an inefficient function it should
never
be used in ruby code.

Ouch. That's a pretty bold claim.

Is inject() too inefficient for use on a ten element Array? How about
three?

Perhaps "never" was the wrong word.

James Edward Gray II
 
D

David Morton

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


Michael said:
yermej said:
I'll offer up an inject version (mostly for novelty's sake):
timing_given.each {|k, v| timing_given[k] = v.inject(Hash.new {|h,
k|
h[k] = []}) {|acc, h| h.each {|k, v| acc[k] << v}; acc}}

Geez - did you use to code perl code? Because Perl code tends to
be as unreadable and compact as yours :)

It works good, but I guess I've got some reading to do, to actually
understand why it's working ;->

Don't bother. inject() is such an inefficient function it should
never
be used in ruby code.


No, it's too slow only if you have profiled a specific application and
the profiling software pegs it as being the culprit. Premature
optimization and all that. If it's only going over a small data set,
it probably doesn't matter. If it *does* matter, then there's
probably a bigger algorithm problem. In the meantime, it presents a
syntactic sugar for some people.

But if that code was sugar, I think there's some vinegar in it ...
inject probably isn't the right answer in terms of maintainability in
this case. After all, yermej said it was for novelty's sake. :)


David Morton
Maia Mailguard http://www.maiamailguard.com
(e-mail address removed)



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)

iD8DBQFHmOq1Uy30ODPkzl0RAiZYAKC+zC1rJxiWCqbAZHec0mRxMJivowCgimmH
+v2xp6hWUwXhRAnxfd6OzPw=
=cTQQ
-----END PGP SIGNATURE-----
 
T

Thufir

This might help, though some would say it's better just to avoid inject
entirely:

timing_given.each do |test_type, test_data|
timing_given[test_type] =
test_data.inject(Hash.new {|h, k| h[k] = []}) do |new_hash,
old_hash|
old_hash.each do |data_field, data_value|
new_hash[data_field] << data_value
end
new_hash
end
end


Why would this be preferable to using a db for storing data? I don't
understand the prevalence of Hash.


-Thufir
 

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,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top