zipWithの自作

id:omochistさんのzipWithを読んで、私も書いてみました。。
対称的じゃないので、きれいじゃないけど、dupしないというメリットはあります。

def zipWith(xs, ys, &block)
  zipped = []
  xs.each_with_index do |x, k|
    zipped << block.call(x, ys[k])
  end
  zipped
end

a = (1..5).to_a
b = (3..7).to_a
p zipWith(a, b) { |x, y| x + y }
#=> [4, 6, 8, 10, 12]

追記:omochistさんから、ysのほうが短いとエラーという指摘がありました。確かに。
追記:通りすがりさんから、Enumerable#zipがあるよと教えていただきました。確かに。
では、zipを使って、さらに複数個のzip_withもできるように。この場合、長さにずれがあると開いたところにはnilが入ってブロックに渡されます。

module Enumerable
  def zip_with(*es, &block)
    zipped = []
    zip(*es) do |args|
      zipped << block.call(*args)
    end
    zipped
  end
end

a = (1..5).to_a
b = (3..7).to_a
c = (101..105).to_a
p a.zip_with(b, c) { |x, y, z| x + y + z }
#=> [105, 108, 111, 114, 117]

追記:すでに同様のコードをsumimさんが書かれていました…。

追記:passerbyさんから。mapか…。みなさんありがとうございます♪

module Enumerable
  def zip_with(*others, &block)
    zip(*others).map &block
  end
end
p (1..5).zip_with(3..7) {|a,b| a+b}
#=> [4, 6, 8, 10, 12]

追記:ttateさんから。