From: Robert Klemme Date: 2008-01-25T23:37:06+09:00 Subject: Re: Changing an array data structure 2008/1/24, 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: 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 -- use.inject do |as, often| as.you_can - without end