[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Change a data structure

Michael Schmarck

1/24/2008 8:15:00 AM

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
9 Answers

7stud --

1/24/2008 10:31:00 AM

0

Michael Schmarck wrote:
> 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]}}
--
Posted via http://www.ruby-....

yermej

1/24/2008 2:56:00 PM

0

On Jan 24, 2:14 am, Michael Schmarck <michael.schma...@here.la> wrote:
> 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}}

Michael Schmarck

1/24/2008 3:04:00 PM

0

7stud -- <bbxx789_05ss@yahoo.com> wrote:

> Try this:

Your code works great - but I changed the data structure in the
meantime, as an Array suits my needs better :( Please see
<news:1441063.yT1qbWcgPr@michael-schmarck.my-fqdn.de>.

Thanks,
Michael

Michael Schmarck

1/24/2008 3:07:00 PM

0

yermej <yermej@gmail.com> wrote:

> 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

yermej

1/24/2008 3:24:00 PM

0

On Jan 24, 9:06 am, Michael Schmarck <michael.schma...@here.la> wrote:
> yermej <yer...@gmail.com> wrote:
> > 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

7stud --

1/24/2008 4:02:00 PM

0

Michael Schmarck wrote:
> yermej <yermej@gmail.com> wrote:
>
>> 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.
--
Posted via http://www.ruby-....

James Gray

1/24/2008 4:11:00 PM

0

On Jan 24, 2008, at 10:02 AM, 7stud -- wrote:

> Michael Schmarck wrote:
>> yermej <yermej@gmail.com> wrote:
>>
>>> 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

David Morton

1/24/2008 7:45:00 PM

0

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


On Jan 24, 2008, at 10:02 AM, 7stud -- wrote:

> Michael Schmarck wrote:
>> yermej <yermej@gmail.com> wrote:
>>
>>> 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.maiamai...
mortonda@dgrmm.net



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

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

Thufir Hawat

2/15/2008 10:30:00 PM

0

On Fri, 25 Jan 2008 00:24:57 +0900, yermej wrote:


> 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