Changing an array data structure

Hello.

I already asked about how I’d best re-order a datastructure. But
thinking about, I changed my mind; instead of the hash approach
I’ve shown in news:[email protected],
I now think I might use arrays instead. Reason: The order in which
something is inserted and later fetched is important to me. With
Hashes in 1.8, this cannot easily be done out-of-the-box, can it?

Anyway - I’m now looking for a way to change the following arry:

timing = [
[“Performance Test of Item Access using Lists”, [
[[“Plants”, 100], [“Customers”, 50], [“Total”, 150]],
[[“Plants”, 85], [“Customers”, 60], [“Total”, 145]],
[[“Plants”, 111], [“Customers”, 77], [“Total”, 188]]
]],
[“Performance Test of Item Access using Advance Item Search”, [
[[“Work List”, 17], [“Bookmarks”, 30], [“Total”, 42]],
[[“Work List”, 10], [“Bookmarks”, 33], [“Total”, 50]],
[[“Work List”, 22], [“Bookmarks”, 27], [“Total”, 99]]
]]
]

This should become:

timing_reordered = [
[“Performance Test of Item Access using Lists”, [
[“Plants”, [100, 85, 111]], [“Customers”, [50, 60, 77]],
[“Total”, [150, 145, 188]]
]],
[“Performance Test of Item Access using Advance Item Search”, [
[“Work List”, [17, 10, 22]], [“Bookmarks”, [30, 33, 27]],
[“Total”, [42, 50, 99]]
]]
]

It very much resembles the datastructure shown in the hash approach.
That’s only natural, if you take into consideration how the data is
generated. To do that, I’m running a method 3 (or more) times; these
methods generate the “Performance Test of Item Access using Lists”
and “Performance Test of Item Access using Advance Item Search” data.
These methods generate data; data items for Plants, Customers and
so on.

But for reporting, it’s best for me, if all the eg. Plants results
are “grouped together”. Actually, I only need the innermost arrays,
ie. [100, 85, 111], [50, 60, 77], … These arrays should be
concated, so that I’ve only got one long array, starting with: [100,
85, 111, 50, 60, 77, …].

Well - how would I reorder the array best? I tried:

    timing.each { |test|
      ...
    }

But actually, I already fail to go on there. Now “test” is an array.
When I access test[0], I get the “category labels” (“Performance
Test of …”) and with test[1], I get the entries. Ie.:

    Plants
    100
    Customers
    50
    Total
    150

If I add another “each loop” into that existing loop, I don’t get
what I’d expect. I tried:

    timing.each { |test|
      test[1].each { |test_values|
        puts test_values[0]
      }
    }

Now I’d expect to get Plants, Customers, Total, Work Lists, Bookmarks,
Total. But I get:

    Plants
    100
    Plants
    85
    Plants
    111
    Work List
    17
    Work List
    10
    Work List
    22

So I only get the 1st “column” of the input data. Why’s that? And
how would I do that correctly, as that’s obviously not the right
way to go?

Thanks again,
Michael

2008/1/24, Michael S. [email protected]:

Hello.

I already asked about how I’d best re-order a datastructure. But
thinking about, I changed my mind; instead of the hash approach
I’ve shown in news:[email protected],
I now think I might use arrays instead. Reason: The order in which
something is inserted and later fetched is important to me. With
Hashes in 1.8, this cannot easily be done out-of-the-box, can it?

Anyway - I’m now looking for a way to change the following arry:

This is not an Array but an object graph composed of nested Arrays.

  ]]

]

This should become:

timing_reordered = [
[“Performance Test of Item Access using Lists”, [
[“Plants”, [100, 85, 111]], [“Customers”, [50, 60, 77]], [“Total”, [150, 145, 188]]
]],
[“Performance Test of Item Access using Advance Item Search”, [
[“Work List”, [17, 10, 22]], [“Bookmarks”, [30, 33, 27]], [“Total”, [42, 50, 99]]
]]
]

My first advice would be to use proper data types, e.g.

S1 = Struct.new :plants, :customers, :total
S2 = Struct.new :work_list, :bookmarks, :total

etc.

It very much resembles the datastructure shown in the hash approach.
That’s only natural, if you take into consideration how the data is
generated. To do that, I’m running a method 3 (or more) times; these
methods generate the “Performance Test of Item Access using Lists”
and “Performance Test of Item Access using Advance Item Search” data.

For these you should use those structs (see above).

These methods generate data; data items for Plants, Customers and
so on.

But for reporting, it’s best for me, if all the eg. Plants results
are “grouped together”. Actually, I only need the innermost arrays,
ie. [100, 85, 111], [50, 60, 77], … These arrays should be
concated, so that I’ve only got one long array, starting with: [100,
85, 111, 50, 60, 77, …].

With the structs above

data contains S1

data.inject(S1.new) do |s,d|
(s.plants ||= []) << d.plants
(s.customers ||= []) << d.customers
(s.total ||= []) << d.total
s
end

Alternatively

data.inject(:plants=>[], :customers=>[], :total=>[]) do |s,d|
d.members.each {|m| s[m.to_sym] = d[m]}
s
end

Of course you need to take additional measures to cope with the
nesting (S1 and S2).

Cheers

robert

Robert K. [email protected] wrote:

Anyway - I’m now looking for a way to change the following arry:
[[“Work List”, 17], [“Bookmarks”, 30], [“Total”, 42]],
[“Performance Test of Item Access using Advance Item Search”, [
[“Work List”, [17, 10, 22]], [“Bookmarks”, [30, 33, 27]],
[[“Total”, [42, 50, 99]]
]]
]

My first advice would be to use proper data types, e.g.

S1 = Struct.new :plants, :customers, :total
S2 = Struct.new :work_list, :bookmarks, :total

Can I automatically create those elements of the Struct? I
don’t want to have to fiddle with the data type, when a new
test comes up. And I’d also like to have easy access to the
name of the test in a well written way (ie. “Work List”).
How do I iterate over the elements of the Struct? I absolutely
do not want to have to rely on knowing the names of all these
data points.

I think I’d be all set, if I could use hashes, because then
I’d have all I need - but in Ruby 1.8, the order of the elements
of a hash is not “stable”. Ie., I “insert” “Work List”, “Bookmarks”
and “Total”, but when I iterate over the hash, I get back “Bookmarks”,
“Work List” and “Total” :frowning: No good :frowning:

As I don’t want to lose the order in which something has been
added to the datastructure, I’m forced to use arrays in Ruby
1.8, aren’t I?

[…]

With the structs above

data contains S1

data.inject(S1.new) do |s,d|
(s.plants ||= []) << d.plants
(s.customers ||= []) << d.customers
(s.total ||= []) << d.total

Urgs. I don’t want to have to know that there’s a “plants”, “customers”,
“total”, etc.pp…

Thanks a lot,

Michael