Creating 2-D array from 1-D array

Hello, I am relatively new to Ruby. I have an existing array:
   a = [1 , 2 , 3 , 4 , 5 , 6]
and I want to create this 2-D array:
   b = [[1 , 2][2 , 4][5 , 6]]
I am using the following code, which works, but seems somewhat clumsy:
    b = Array.new
    i = 0
    k = 0
    for item in a
      if i == 0
        a1 = item
        i = 1
      elsif i == 1
        a2 = item
        i = 0
        b[k] = [a1, a2]
        puts "b..#{k}, #{b[k]}"
        k = k + 1
      end
    end
I would appreciate any advice to make this code look more elegant or
ruby-like. In particular, I suspect there is a way to avoid the
indices.
Thanks for the help.

···

--
Posted via http://www.ruby-forum.com/.

Here are some suggestions, which should help reduce the use of indices
and local variables.

When constructing the array b, you don't need to reference a position.
You can start with an empty array, and push the new pairs onto the end:

instead of b = Array.new, write b = []
instead of b[k] = [a1, a2], write b << [a1, a2]

That gets rid of k.

To get the pairs, I suggest you investigate 'slice'.

e.g. a.slice(0, 2) returns a two-element array from the 0th position of

You will also need to change your looping mechanism if you use slice,
but you should be able to get rid of a1 and a2.

···

a: [1, 2]

--
Posted via http://www.ruby-forum.com/.

Thanks a lot for the suggestions.
I also found a good tip at:
http://www.java2s.com/Code/Ruby/Array/Stepwitharray.htm
Now my code looks like:
  a = [1 , 2 , 3 , 4 , 5 , 6]
  b = []
  (0..a.length-1).step(2) do |i|
    b << [a[i], a[i+1]]
  end
  print b
There might also be a simple solution using slice, need to work on it.
Much better! Thanks again

···

--
Posted via http://www.ruby-forum.com/.

# There are some very helpful methods in Enumerable
# (Module: Enumerable — Documentation for core (1.9.3)).
# In this case, check out each_slice.

ary = [1 , 2 , 3 , 4 , 5 , 6]
sliced = ary.each_slice 2

sliced # => #<Enumerator: [1, 2, 3, 4, 5, 6]:each_slice(2)>

# You can think of it like the array you showed,
# for instance you can iterate over its elements
# or map them to new values or whatever.

sliced.each do |element|
  element # => [1, 2], [3, 4], [5, 6]
end

sliced.map(&:reverse) # => [[2, 1], [4, 3], [6, 5]]

# But if you really need an array, you can get it with to_a

sliced.to_a # => [[1, 2], [3, 4], [5, 6]]

···

On Sun, Nov 27, 2011 at 7:06 AM, J. Marshal <windbreiz@gmail.com> wrote:

Hello, I am relatively new to Ruby. I have an existing array:
  a = [1 , 2 , 3 , 4 , 5 , 6]
and I want to create this 2-D array:
  b = [[1 , 2][2 , 4][5 , 6]]
I am using the following code, which works, but seems somewhat clumsy:
   b = Array.new
   i = 0
   k = 0
   for item in a
     if i == 0
       a1 = item
       i = 1
     elsif i == 1
       a2 = item
       i = 0
       b[k] = [a1, a2]
       puts "b..#{k}, #{b[k]}"
       k = k + 1
     end
   end
I would appreciate any advice to make this code look more elegant or
ruby-like. In particular, I suspect there is a way to avoid the
indices.
Thanks for the help.

--
Posted via http://www.ruby-forum.com/\.

Many thanks for the tips. You guys are great!

···

--
Posted via http://www.ruby-forum.com/.

You can also use Hash constructor:

a = [1 , 2 , 3 , 4 , 5 , 6]
siliced = Hash[*a].to_a

Sandro

···

On Sunday, November 27, 2011, Josh Cheek <josh.cheek@gmail.com> wrote:

On Sun, Nov 27, 2011 at 7:06 AM, J. Marshal <windbreiz@gmail.com> wrote:

Hello, I am relatively new to Ruby. I have an existing array:
  a = [1 , 2 , 3 , 4 , 5 , 6]
and I want to create this 2-D array:
  b = [[1 , 2][2 , 4][5 , 6]]
I am using the following code, which works, but seems somewhat clumsy:
   b = Array.new
   i = 0
   k = 0
   for item in a
     if i == 0
       a1 = item
       i = 1
     elsif i == 1
       a2 = item
       i = 0
       b[k] = [a1, a2]
       puts "b..#{k}, #{b[k]}"
       k = k + 1
     end
   end
I would appreciate any advice to make this code look more elegant or
ruby-like. In particular, I suspect there is a way to avoid the
indices.
Thanks for the help.

--
Posted via http://www.ruby-forum.com/\.

# There are some very helpful methods in Enumerable
# (Module: Enumerable — Documentation for core (1.9.3)).
# In this case, check out each_slice.

ary = [1 , 2 , 3 , 4 , 5 , 6]
sliced = ary.each_slice 2

sliced # => #<Enumerator: [1, 2, 3, 4, 5, 6]:each_slice(2)>

# You can think of it like the array you showed,
# for instance you can iterate over its elements
# or map them to new values or whatever.

sliced.each do |element|
element # => [1, 2], [3, 4], [5, 6]
end

sliced.map(&:reverse) # => [[2, 1], [4, 3], [6, 5]]

# But if you really need an array, you can get it with to_a

sliced.to_a # => [[1, 2], [3, 4], [5, 6]]

You can also use Hash constructor:

a = [1 , 2 , 3 , 4 , 5 , 6]
siliced = Hash[*a].to_a

Beware that this will only work if the odd elements are unique.

Hash[*[1,2,1,3,1,4]].to_a

=> [[1, 4]]

···

On Sun, Nov 27, 2011 at 4:50 PM, Sandro Paganotti <sandro.paganotti@gmail.com> wrote:

Sandro

On Sunday, November 27, 2011, Josh Cheek <josh.cheek@gmail.com> wrote:

On Sun, Nov 27, 2011 at 7:06 AM, J. Marshal <windbreiz@gmail.com> wrote:

Hello, I am relatively new to Ruby. I have an existing array:
a = [1 , 2 , 3 , 4 , 5 , 6]
and I want to create this 2-D array:
b = [[1 , 2][2 , 4][5 , 6]]
I am using the following code, which works, but seems somewhat clumsy:
b = Array.new
i = 0
k = 0
for item in a
if i == 0
a1 = item
i = 1
elsif i == 1
a2 = item
i = 0
b[k] = [a1, a2]
puts "b..#{k}, #{b[k]}"
k = k + 1
end
end
I would appreciate any advice to make this code look more elegant or
ruby-like. In particular, I suspect there is a way to avoid the
indices.
Thanks for the help.

--
Posted via http://www.ruby-forum.com/\.

# There are some very helpful methods in Enumerable
# (http://rubydoc.info/stdlib/core/1.9.3/Enumerable\).
# In this case, check out each_slice.

ary = [1 , 2 , 3 , 4 , 5 , 6]
sliced = ary.each_slice 2

sliced # => #<Enumerator: [1, 2, 3, 4, 5, 6]:each_slice(2)>

# You can think of it like the array you showed,
# for instance you can iterate over its elements
# or map them to new values or whatever.

sliced.each do |element|
element # => [1, 2], [3, 4], [5, 6]
end

sliced.map(&:reverse) # => [[2, 1], [4, 3], [6, 5]]

# But if you really need an array, you can get it with to_a

sliced.to_a # => [[1, 2], [3, 4], [5, 6]]

--
Michael Fellinger
CTO, The Rubyists, LLC