Two-dimensional array in Ruby

Asked

Viewed 281 times

2

I have the two-dimensional array

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

and 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 content each index of the new array(Ex: ["a", "b"] matches the first item of the array to (a[0][0] and a[1][0]...etc), I did this to try to resolve the issue:

  • 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' from the third index of array b, is going to index 2 and the next progressing 4 is coming out like this...

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

I think it might be a simple thing on this index, but I’m already mixing things up.

2 answers

4


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

The code below creates elements in b for each index found in the elements of a. Then add to this element in b the elements found in a for 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"]]
  • 1

    Wow, very good Guigs, practical solution d+, thank you very much. To get to a place we have several paths, but I was trying a difficult path, so I did not arrive, I’m learning Ruby and it makes me more passionate about this language.

1

The beautiful thing about Ruby is that almost all these types of processing can be written in one line, 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 build a value iteratively. You pass the value as argument and, at each iteration, receive the current value and an argument and 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 use the inject! also to apply the modification inplace.

  • No wonder I love this language, various ways to get a result, this so of inject is ninja.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.