Reputation: 760
Let's say I have an array
arr1 = ["a", "b", "c"]
and I want to zip an array of arrays to it
arr2 = [[1, "foo"], [2, "bar"], [3, "baz"]]
so that the end result is
[["a", 1, "foo"], ["b", 2, "bar"], ["c", 3, "baz"]]
Right now what I'm doing is arr1.zip(arr2).map!(&:flatten)
, but I'm wondering if there's a better way to do this?
Upvotes: 6
Views: 718
Reputation: 11403
If you need the content of arr2
to be before the content of arr1
, you cannot use the #transpose
trick. However, you can:
arr1.map.with_index { |el, i| [*arr2[i], el] }
# => [[1, "foo", "a"], [2, "bar", "b"], [3, "baz", "c"]]
Which has the perks of:
In terms of performance, Doguita's answer seems better:
arr1 = %w(foo) * 10_000
arr2 = arr1.length.times.map { |i| [i, i.to_s(2)] }
Benchmark.bmbm(20) do |x|
x.report("zip & transpose:") { arr1.zip(*arr2.transpose) }
x.report("map & with_index:") { arr1.map.with_index { |v, i| [v, *arr2[i]] } }
end
Rehearsal --------------------------------------------------------
zip & transpose: 0.000902 0.000233 0.001135 ( 0.001107)
map & with_index: 0.004206 0.002308 0.006514 ( 0.006828)
----------------------------------------------- total: 0.007649sec
user system total real
zip & transpose: 0.001474 0.000045 0.001519 ( 0.001471)
map & with_index: 0.002155 0.000059 0.002214 ( 0.002282)
Upvotes: 1
Reputation: 110725
Here are two other (closely-related) ways:
enum = arr1.to_enum
arr2.map { |a| [enum.next].concat(a) }
#=> [["a", 1, "foo"], ["b", 2, "bar"], ["c", 3, "baz"]]
or
arr1_cpy = arr1.dup
arr2.map { |a| [arr1_cpy.shift].concat(a) }
#=> [["a", 1, "foo"], ["b", 2, "bar"], ["c", 3, "baz"]]
Upvotes: 3
Reputation: 2621
arr2.each_with_index{ |el,i| el.unshift(arr1[i]) }
Maybe you like that better?
Upvotes: 1
Reputation: 15723
Another way is:
arr1.zip(*arr2.transpose)
# => [["a", 1, "foo"], ["b", 2, "bar"], ["c", 3, "baz"]]
Upvotes: 13