Two-dimensional array in Ruby

2

I have the two-dimensional array

a = [[1,'a'],[1,'b'],[2,'c'],[2,'d'],[3,'e'],[3,'f'],[4,'g'],[4,'h']] 

I want to separate the letters in another array b so that it looks like this:

[["a","b"], ["c", "d"], ["e", "f"], ["g", "h"]] 

Where the contents of each index of the new array (Ex: ["a", "b"] matches the first array item a ( a[0][0] and a[1][0] ... etc), I did this to try to solve the question:

  • first created the two-dimensional array

    for i in (1..4)
      b[i] = Array.new
    end
    
  • Then the code

    c = 0
    x = 0
    a.each do |k|
      if  k[0] == a[x+1][0]
        b[k[0]][c] = k[1]
        c += 1
        x += 1
      else      
        b[k[0]][c] = k[1]
        c = 0
      end
    end
    

The problem is the index 'c' that from the third index of the array b, is going to index 2 and the next the 4 in progression coming out like this ...

[nil, ["a", "b"], ["c", "d"], [nil, nil, "e", "f"], [nil, nil, nil, nil, "g", "h"]]

I think it may be a simple thing in this index, but I'm already mixing things up.

    
asked by anonymous 21.05.2014 / 03:54

2 answers

4

Try to use less index manipulation, which makes the code confusing. Usually Ruby allows this.

The code below creates elements in b for each index found in a elements. Then it adds to that element in b the elements found in a to that index.

a = [[1,'a'],[1,'b'],[2,'c'],[2,'d'],[3,'e'],[3,'f'],[4,'g'],[4,'h']] 
b = Array.new
a.each do |k|
  b[k[0]] ||= Array.new
  b[k[0]] << k[1]
end
b # => [nil, ["a", "b"], ["c", "d"], ["e", "f"], ["g", "h"]]
    
21.05.2014 / 13:48
1

The beautiful ruby is that almost all of these types of processing can be written in a row, without using loops directly. It's like working with a functional language. Note:

a = [[1,'a'],[1,'b'],[2,'c'],[2,'d'],[3,'e'],[3,'f'],[4,'g'],[4,'h']]
result = a.inject([]) {|r, k| r[k[0]] ||= []; r[k[0]] << k[1]; r }

Inject serves to construct a value iteratively. You pass the value as argument and, at each iteration, it receives the current value and an argument and must return the next value. A little more explained:

result = a.inject([]) do |temp, element|
   index, value = element
   temp[index] ||= []
   temp[index] << value
   temp
end

You can also use inject! to apply the inplace modification.

    
21.05.2014 / 15:09