Project

General

Profile

Actions

Feature #8970

open

Array.zip and Array.product

Added by sawa (Tsuyoshi Sawada) about 11 years ago. Updated about 5 years ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:57498]

Description

=begin
Most of the time when I use Array#zip or Array#product, I feel cumbursome that I have to take out the first array and pass it as a receiver. For example, if I have

a = [[:a, :b, :c], [:d, :e, :f], [:g, :h, :i]]

I have to do something like this:

a.first.zip(*a.drop(1)){...}
a.first.product(*a.drop(1)){...}

Sometimes, the receiver (i.e., the first array) has significance, but most other times, that breaks asymmetry, making the code look ugly.

I would be happy if we had Array.zip and Array.product in addition so that we can do it like this:

Array.zip(*a){...}
Array.product(*a){...}

=end


Related issues 3 (2 open1 closed)

Related to Ruby master - Feature #19324: Enumerator.product => Enumerable#productAssignedknu (Akinori MUSHA)Actions
Has duplicate Ruby master - Feature #6499: Array::zipRejectedmatz (Yukihiro Matsumoto)05/26/2012Actions
Is duplicate of Ruby master - Feature #7444: Array#product_setAssignedmatz (Yukihiro Matsumoto)Actions

Updated by akr (Akira Tanaka) about 11 years ago

2013/10/1 sawa (Tsuyoshi Sawada) :

Feature #8970: Array.zip and Array.product
https://bugs.ruby-lang.org/issues/8970

Most of the time when I use Array#zip or Array#product, I feel cumbursome that I have to take out the first array and pass it as a receiver. For example, if I have

a = [[:a, :b, :c], [:d, :e, :f], [:g, :h, :i]]

I have to do something like this:

a.first.zip(*a.drop(1)){...}
a.first.product(*a.drop(1)){...}

Sometimes, the receiver (i.e., the first array) has significance, but most other times, that breaks asymmetry, making the code look ugly.

I would be happy if we had Array.zip and Array.product in addition so that we can do it like this:

Array.zip(*a){...}
Array.product(*a){...}

How different with Array#transpose ?

% ruby -e '
a = [[:a, :b, :c], [:d, :e, :f], [:g, :h, :i]]
p a.first.zip(*a.drop(1))
p a.transpose
'
[[:a, :d, :g], [:b, :e, :h], [:c, :f, :i]]
[[:a, :d, :g], [:b, :e, :h], [:c, :f, :i]]

Tanaka Akira

Updated by sawa (Tsuyoshi Sawada) about 11 years ago

akr, The difference between Array#transpose and Array.zip is just the same as with Array#transpose and Array#zip. That is, when any non-first array is shorter than the first, it is complemented with nil.

Updated by sowieso (So Wieso) over 10 years ago

+1
This would make code more readable by not breaking the symmetry.
Also would be nice if the block version wouldn't return nil, but instead the concatenation of all return values, like map does. (not that an explicit map would hurt, but this is a waste of a return value)

Array.zip([1,2,3],[4,5,6]){|left,right| left + right} => [5,7,9]

Updated by marcandre (Marc-Andre Lafortune) over 10 years ago

Updated by marcandre (Marc-Andre Lafortune) over 10 years ago

Updated by osyo (manga osyo) about 5 years ago

If you use https://bugs.ruby-lang.org/issues/15955, you can write as follows.

class UnboundMethod
  # apply or other name
  def apply(receiver, *args)
    bind(receiver).call(*args)
  end
end

arrays = [["a", "b"], ["c"], ["d", "e"]]

p Array.instance_method(:product).apply(*arrays)
# => [["a", "c", "d"], ["a", "c", "e"], ["b", "c", "d"], ["b", "c", "e"]]

p Array.instance_method(:zip).apply(*arrays)
# => [["a", "c", "d"], ["b", nil, "e"]]

Need a syntax to call instance_method like .: ?

Updated by sawa (Tsuyoshi Sawada) about 5 years ago

osyo (manga osyo) wrote:

If you use https://bugs.ruby-lang.org/issues/15955, you can write as follows.

class UnboundMethod
  # apply or other name
  def apply(receiver, *args)
    bind(receiver).call(*args)
  end
end

arrays = [["a", "b"], ["c"], ["d", "e"]]

p Array.instance_method(:product).apply(*arrays)
# => [["a", "c", "d"], ["a", "c", "e"], ["b", "c", "d"], ["b", "c", "e"]]

p Array.instance_method(:zip).apply(*arrays)
# => [["a", "c", "d"], ["b", nil, "e"]]

Need a syntax to call instance_method like .: ?

Thank you for the suggestion, but that looks a little too long. It can also be written as:

:product.to_proc.(*arrays)
# => [["a", "c", "d"], ["a", "c", "e"], ["b", "c", "d"], ["b", "c", "e"]]

:zip.to_proc.(*arrays)
# => [["a", "c", "d"], ["b", nil, "e"]]

But the proposal here seems to be favored more at least by mame-san (#16102).

Actions #9

Updated by duerst (Martin Dürst) almost 2 years ago

  • Related to Feature #19324: Enumerator.product => Enumerable#product added
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0