Help with Multi Dimensional Array

Discussion in 'Ruby' started by lionbarrage, Feb 25, 2009.

  1. lionbarrage

    lionbarrage Guest

    I'm new to ruby and have been trying to figure out what I'm doing
    wrong.

    I'm completely stumped about how to merge two files together based on
    whether they share the same key or not.

    Example:

    File 1
    ALPHA|OMEGA|GAMMA
    1 | 2 | 3
    4| 5| 6

    File 2
    EPSILON|GREEK|OMEGA|BETA
    7| 8| 9| 0
    12| | 13|
    10| 11| 5| 15

    End result should be:

    ALPHA|OMEGA|GAMMA|EPSILON|GREEK|BETA
    1 | 2 | 3 |
    | |
    4 | 5 | 6 | 10|
    11| 15
    | 9| | 7|
    8| 0
    | 13| | 12|
    |



    Currently I have tried this:

    array_file1 = []
    array_file2 = []

    row = 0
    IO.foreach("file1.txt" ) {
    |line|
    array_file1[row] = line.split("|")
    row += 1
    }

    row = 0
    IO.foreach("file2" ) {
    |line|
    array_file2[row] = line.split("|")
    row += 1
    }
    N = array_file1.length
    array_file1.times(N) { |row|
    if array_file1[row][1] == array_file2[row][2]
    array_file2[row].each{
    |col|
    array_file1[row][array_file1i[row].length] = col
    }
    end
    }

    But I get Undefined Method

    Logically, I want to
    loop through row of array_file 1{
    check to see if array_file1.OMEGA is equal to array_file2.OMEGA
    loop through column
    insert contents of array_file2 to end of array_file1
    end loop
    end loop


    Any help would be greatly appreciated!
    lionbarrage, Feb 25, 2009
    #1
    1. Advertising

  2. lionbarrage

    7stud -- Guest

    lionbarrage wrote:
    >
    > File 1
    > ALPHA|OMEGA|GAMMA
    > 1 | 2 | 3
    > 4| 5| 6
    >
    > File 2
    > EPSILON|GREEK|OMEGA|BETA
    > 7| 8| 9| 0
    > 12| | 13|
    > 10| 11| 5| 15
    >
    > End result should be:
    >
    > ALPHA|OMEGA|GAMMA|EPSILON|GREEK|BETA
    > 1 | 2 | 3 |
    > | |
    > 4 | 5 | 6 | 10|
    > 11| 15
    > | 9| | 7|
    > 8| 0
    > | 13| | 12|
    > |
    >



    Wow. What made you think you could tackle ascii art? And were you
    actually satisfied with the result?
    --
    Posted via http://www.ruby-forum.com/.
    7stud --, Feb 25, 2009
    #2
    1. Advertising

  3. * lionbarrage <> (02:17) schrieb:

    > File 1
    > ALPHA|OMEGA|GAMMA
    > 1 | 2 | 3
    > 4 | 5 | 6
    >
    > File 2
    > EPSILON|GREEK|OMEGA|BETA
    > 7 | 8 | 9 | 0
    > 12 | | 13 |
    > 10 | 11 | 5 | 15
    >
    > End result should be:
    >
    > ALPHA|OMEGA|GAMMA|EPSILON|GREEK|BETA
    > 1 | 2 | 3 | | |
    > 4 | 5 | 6 | 10 | 11 | 15
    > | 9 | | 7 | 8 | 0
    > | 13 | | 12 | |


    I hoped I fixed your ASCII art the right way.

    In understand that this represents named sets of integers that are to be
    merged. Right?

    The natural representation of that would be a hash containing sets.
    There is a set class, but I use arrays here:

    require 'pp'

    sets = Hash.new { | h, k | h[k] = [] } # hash that contains a new array
    # for every new key
    %w(file1.txt file2).each do | filename |
    File.open(filename) do | f |
    names = f.gets.chop.split('|')
    f.each do | line |
    names.zip(line.chop.split('|')).each do | name, value |
    sets[name] << value
    end
    end
    end
    end

    pp sets

    This code does no tabular printing, treats the "integers" as strings,
    without excluding empty strings and doubles. But that could easily be
    fixed.

    Probably I got it all wrong. :-(

    mfg, simon .... l
    Simon Krahnke, Feb 25, 2009
    #3
  4. lionbarrage

    lionbarrage Guest

    On Feb 24, 8:58 pm, Simon Krahnke <> wrote:
    > * lionbarrage <> (02:17) schrieb:
    >
    >
    >
    > > File 1
    > > ALPHA|OMEGA|GAMMA
    > >           1 |         2 |           3
    > >           4 |         5 |           6

    >
    > > File 2
    > > EPSILON|GREEK|OMEGA|BETA
    > >           7 |         8 |           9 |       0
    > >          12 |           |          13 |
    > >          10 |        11 |           5 |      15

    >
    > > End result should be:

    >
    > > ALPHA|OMEGA|GAMMA|EPSILON|GREEK|BETA
    > >           1 |         2 |           3 |         |          |
    > >           4 |         5 |           6 |      10 |       11 |     15
    > >             |         9 |             |       7 |        8 |      0
    > >             |        13 |             |      12 |          |

    >
    > I hoped I fixed your ASCII art the right way.
    >
    > In understand that this represents named sets of integers that are to be
    > merged. Right?
    >
    > The natural representation of that would be a hash containing sets.
    > There is a set class, but I use arrays here:
    >
    > require 'pp'
    >
    > sets = Hash.new { | h, k | h[k] = [] } # hash that contains a newarray
    >                                        # for every new key
    > %w(file1.txt file2).each do | filename |
    >   File.open(filename) do | f |
    >     names = f.gets.chop.split('|')
    >     f.each do | line |
    >        names.zip(line.chop.split('|')).each do | name, value |
    >          sets[name] << value
    >        end
    >     end
    >   end
    > end
    >
    > pp sets
    >
    > This code does no tabular printing, treats the "integers" as strings,
    > without excluding empty strings and doubles. But that could easily be
    > fixed.
    >
    > Probably I got it all wrong. :-(
    >
    > mfg,                        simon .... l


    Thanks for fixing my art, looked fine in my screen but I guess the
    translation was off.

    I'm not too familiar with hashes but the code you wrote seems to be
    doing it. Thank you so much!!

    How do i refer to a single element within a hash? Let's say I want
    11 for example. Would I do sets["GREEK"][3]?

    THANK YOU!
    lionbarrage, Feb 26, 2009
    #4
  5. * lionbarrage <> (08:11) schrieb:

    > I'm not too familiar with hashes but the code you wrote seems to be
    > doing it. Thank you so much!!


    Hashes are just like arrays, only the keys can be anything and not just
    integers.

    > How do i refer to a single element within a hash?


    Simply by sets['GREEK'], but that single element is an array.

    > Let's say I want 11 for example. Would I do sets["GREEK"][3]?


    Yes, sets['GREEK'][1] should do.

    mfg, simon .... l
    Simon Krahnke, Feb 26, 2009
    #5
  6. lionbarrage

    lionbarrage Guest

    On Feb 26, 4:51 am, Simon Krahnke <> wrote:
    > * lionbarrage <> (08:11) schrieb:
    >
    > > I'm not too familiar with hashes but the code you wrote seems to be
    > > doing it. Thank you so much!!

    >
    > Hashes are just like arrays, only the keys can be anything and not just
    > integers.
    >
    > > How do i refer to a single element within a hash?

    >
    > Simply by sets['GREEK'], but that single element is anarray.
    >
    > > Let's say I want 11 for example.  Would I do sets["GREEK"][3]?

    >
    > Yes, sets['GREEK'][1] should do.
    >
    > mfg,                       simon .... l



    Thanks! I did:
    sets.keys.each{|k|
    print k, "|"
    }
    print "\n"
    sets.values.each { |v|
    pp v
    }
    which got me:

    ALPHA|OMEGA|GAMMA|EPSILON|GREEK|BETA|
    ["1", "4"]
    ["2", "5", "9", "13", "5"]
    ["3", nil]
    ["7", "12", "10"]
    ["8", "", "11"]
    ["0", nil, "1"]

    Is there a format function which will remove "" and change , to | ?

    Thanks tons!
    lionbarrage, Feb 27, 2009
    #6
  7. * lionbarrage <> (2009-02-27) schrieb:

    > Thanks! I did:
    > sets.keys.each{|k|
    > print k, "|"
    > }
    > print "\n"


    You could just do

    puts set.keys.join('|')

    To have the value output you specified in you original post, is a little
    more complicated.

    > Is there a format function which will remove "" and change , to | ?


    Don't use pp for production use. Do your own formatting. Here's my
    updated script:

    ,----[ sets.rb ]
    | #!/usr/bin/env ruby
    |
    | sets = Hash.new { | h, k | h[k] = [] } # hash that contains a new array
    | # for every new key
    | %w(file1.txt file2).each do | filename |
    | File.open(filename) do | f |
    | names = f.gets.chop.split('|')
    | f.each do | line |
    | names.zip(line.chop.split('|')).each do | name, value |
    | sets[name] << value.to_i if value and value !~ /^\s*$/
    | end
    | end
    | end
    | end
    |
    | sets.values.each { | a | a.uniq! }
    |
    | puts sets.keys.map { | k | '%8s ' % k }.join('|')
    |
    | rows = sets.values.map { | a | a.size }.max
    |
    | (1..rows).zip(*sets.values) do | row |
    | row.shift
    | puts row.map { | v | if v then '%8s ' % v else ' '*9 end }.join('|')
    | end
    `----

    ,----[ output ]
    | GAMMA | OMEGA | GREEK | BETA | ALPHA | EPSILON
    | 3 | 2 | 8 | 0 | 1 | 7
    | 6 | 5 | 11 | 15 | 4 | 12
    | | 9 | | | | 10
    | | 13 | | | |
    `----

    If you don't understand the code, please ask.

    mfg, simon .... l
    Simon Krahnke, Feb 28, 2009
    #7
  8. * Simon Krahnke <> (2009-02-28) schrieb:

    >| puts row.map { | v | if v then '%8s ' % v else ' '*9 end }.join('|')


    Actually, since nil.to_s == "" you can do this simpler:

    | puts row.map { | v | '%8s ' % v }.join('|')

    mfg, simon .... l
    Simon Krahnke, Mar 2, 2009
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. kk_oop
    Replies:
    1
    Views:
    2,164
  2. Venkat
    Replies:
    4
    Views:
    972
    Venkat
    Dec 5, 2003
  3. Victor Reyes

    Help defining multi-dimensional array

    Victor Reyes, Dec 8, 2005, in forum: Ruby
    Replies:
    5
    Views:
    109
    Victor Reyes
    Dec 11, 2005
  4. Wirianto Djunaidi
    Replies:
    2
    Views:
    200
    Wirianto Djunaidi
    Apr 29, 2008
  5. news-acct
    Replies:
    6
    Views:
    159
    A. Sinan Unur
    Aug 28, 2005
Loading...

Share This Page