Changing an array data structure

M

Michael Schmarck

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 <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
 
R

Robert Klemme

2008/1/24 said:
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 <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.
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]]
]]
]

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
 
M

Michael Schmarck

Robert Klemme said:
2008/1/24 said:
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 <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.
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]]
]]
]

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" :( No good :(

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
 

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,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top