2

Hello I have the following two arrays in ruby

A=["a","b","c"]
B=["d","e","f"]

and I want to produce this

C = ["ad", "be", "cf"]

regardless of array length. The two arrays are always the same length though.

Is there a neat way to do this? I mean instead of iterating through the arrays with a for loop.

Tasos
  • 1,575
  • 5
  • 18
  • 44

3 Answers3

6

Very simple with the method Array#zip and Array#map :

A = ["a","b","c"]
B = ["d","e","f"]
A.zip(B).map { |a| a.join }
# => ["ad", "be", "cf"]
# or
A.zip(B).map(&:join)
# => ["ad", "be", "cf"]

One more way ( but not looks good ), :-)

A.map.with_index { |e,i| e + B[i] }
# => ["ad", "be", "cf"]
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
  • So zip does: [["a","d"],["b","e"],["c","f"]] and then map takes each smaller array and replaces it with its joint form right? I'm not getting the second solution though, what does &: do? Edit: I actually thought of the third one, but I didn't like it either and then I came here :) – Tasos Mar 10 '14 at 22:26
  • 1
    @Crone For now..if you new to Ruby go with first version of `zip`. And for your interest of the second version - see this - http://stackoverflow.com/questions/1961030/ruby-ampersand-colon-shortcut or all such [related posts](http://stackoverflow.com/search?q=[ruby]+%22%26%3A%22) – Arup Rakshit Mar 10 '14 at 22:31
  • 1
    Actually the third solution is the faster one (~x2), although a bit more ugly. This is the reason why I asked this question: http://stackoverflow.com/questions/22290572/functional-programming-style-vs-performance-in-ruby – Rafa Paez Mar 10 '14 at 22:46
2

As an alternative to zip, you can use transpose which raises an exception if the two arrays aren't the same cardinality.

[A,B].transpose.map(&:join)
Mike Campbell
  • 7,921
  • 2
  • 38
  • 51
2

Just for the record, a benchmark with the different listed solutions. Results:

                              user     system      total        real
Map with index            1.120000   0.000000   1.120000 (  1.113265)
Each with index and Map   1.370000   0.000000   1.370000 (  1.375209)
Zip and Map {|a|}         1.950000   0.000000   1.950000 (  1.952049)
Zip and Map (&:)          1.980000   0.000000   1.980000 (  1.980995)
Transpose and Map (&:)    1.970000   0.000000   1.970000 (  1.976538)

Benchmark

require 'benchmark'

N = 1_000_000
A = ["a","b","c"] 
B = ["d","e","f"]

Benchmark.bmbm(20) do |x|
  x.report("Map with index") do
    N.times do |index|
      A.map.with_index { |e, i| e + B[i] } 
    end
  end

  x.report("Each with index and Map") do
    N.times do |index|
      A.each_with_index.map { |e, i| e + B[i] } 
    end
  end

  x.report("Zip and Map {|a|}") do
    N.times do |index|
      A.zip(B).map { |a| a.join }
    end
  end

  x.report("Zip and Map (&:)") do
    N.times do |index|
      A.zip(B).map(&:join) 
    end
  end

  x.report("Transpose and Map (&:)") do
    N.times do |index|
      [A,B].transpose.map(&:join)
    end
  end
end
Rafa Paez
  • 4,820
  • 18
  • 35