Project

General

Profile

Actions

Feature #5133

open

Array#unzip as an alias of Array#transpose

Added by mrkn (Kenta Murata) over 12 years ago. Updated 7 days ago.

Status:
Assigned
Target version:
-
[ruby-dev:44304]

Description

Array#zip の逆は Array#transpose なんですけど、
この対応関係が非常に分かり難いなと思いました。

Haskell には zip の逆をやる関数として unzip が用意されています。
unzip という名前は、「zip の逆をやりたい」と思ったときに
(transpose よりは) 思い付きやすい名前だと思います。

ということで Array#unzip を Array#transpose のエイリアスとして
導入してはどうでしょう?

以下パッチです:

diff --git a/array.c b/array.c
index 8caad66..dc411b7 100644
--- a/array.c
+++ b/array.c
@@ -4720,6 +4720,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);

  • rb_define_alias(rb_cArray, "unzip", "transpose");
    rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
    rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
    rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);

Updated by znz (Kazuhiro NISHIYAMA) over 12 years ago

逆とはどういう動作のことを言っていますか?

Array#zip が複数の配列から1つの配列を返す(かブロックを受け取ると別の動作)で、
Array#transpose が1つの配列から1つの配列を返す(ブロックは受け取らない)ということから
逆という印象は受けなかったので、逆というだけの説明だとよくわかりませんでした。

Updated by metanest (Makoto Kishimoto) over 12 years ago

きしもとです

[1, 2, 3, 4] と ["a", "b", "c", "d"] から、
[[1, "a"], [2, "b"], [3, "c"], [4, "d"]] を作るのが zip で、

irb> [1, 2, 3, 4].zip ["a", "b", "c", "d"]
=> [[1, "a"], [2, "b"], [3, "c"], [4, "d"]]

[[1, "a"], [2, "b"], [3, "c"], [4, "d"]] を transpose すると、
[[1, 2, 3, 4], ["a", "b", "c", "d"]] が得られるわけですが、

irb> [[1, "a"], [2, "b"], [3, "c"], [4, "d"]].transpose
=> [[1, 2, 3, 4], ["a", "b", "c", "d"]]

なんとなく、たまたま、という気がします。

transpose は自己双対で、zip と双対というわけでもないので、
エイリアスには反対、かなぁ。

[[1, 2, 3], [4, 5, 6], [7, 8, 9]].transpose に対応するものって

zip で簡単にできましたっけ?

というわけで、ドキュメント等にわかりやすく書いておくことについては
賛成します。

Updated by naruse (Yui NARUSE) over 12 years ago

(2011/08/01 20:54), KISHIMOTO, Makoto wrote:

transpose は自己双対で、zip と双対というわけでもないので、
エイリアスには反対、かなぁ。

[[1, 2, 3], [4, 5, 6], [7, 8, 9]].transpose に対応するものって

zip で簡単にできましたっけ?

irb(main):001:0> a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]].transpose
=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
irb(main):002:0> a.zip
=> [[[1, 4, 7]], [[2, 5, 8]], [[3, 6, 9]]]
irb(main):003:0> a[0].zip(*a[1,2])
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

ですね。
簡単っちゃ簡単だけど、ちょっと軸はずれてますね

--
NARUSE, Yui

Updated by mrkn (Kenta Murata) over 12 years ago

「zip が transpose の逆になっているか」
を確認せず投稿したことがバレてしまいましたね。

私が欲しかったのは unzip のような zip の逆っぽいイメージの名前が付いている、
zip する前の配列のセットが返ってくるメソッドです。

きしもとさんの

transpose は自己双対で、zip と双対というわけでもないので、
エイリアスには反対、かなぁ。

という意見については、確かにその通りだと思いましたので、
エイリアスではない方法で導入できるなら嬉しいです。

Actions #5

Updated by shyouhei (Shyouhei Urabe) about 12 years ago

  • Status changed from Open to Assigned

Updated by ko1 (Koichi Sasada) over 11 years ago

  • Assignee changed from matz (Yukihiro Matsumoto) to mrkn (Kenta Murata)
  • Target version changed from 2.0.0 to 2.6

ええと,まつもとさんアサインで進むのだろうか?
mrkn さんがまつもとさんを説得して,next minor から 2.0 に戻して下さい.

Actions #7

Updated by naruse (Yui NARUSE) over 6 years ago

  • Target version deleted (2.6)

Updated by duerst (Martin Dürst) 7 days ago

In issue #20336, @matheusrich (Matheus Richard) wrote:

* [Feature #5133] Array#unzip as an alias of Array#transpose
  * Seems a more friendly name for this method (easier if you don't have a strong math background)
  * It is nice that we can do an operation an reverse it with two similar-named methods:
    ```rb
    [1, 2, 3, 4].zip(["a", "b", "c", "d"], ["I", "II", "III", "IV"])
    # => [[[1, "a"], "I"], [[2, "b"], "II"], [[3, "c"], "III"], [[4, "d"], "IV"]]
    [[[1, "a"], "I"], [[2, "b"], "II"], [[3, "c"], "III"], [[4, "d"], "IV"]].unzip
    # => [[1, 2, 3, 4], ["a", "b", "c", "d"], ["I", "II", "III", "IV"]]

It's already alluded in some of the comments above: transpose is it's own inverse, so if we define unzip as an alias for transpose, unzip will be its own inverse.

The reason Haskell has zip/unzip as inverses is that zip in Haskell converts from two lists to a list of pairs, and unzip converts from a list of pairs to a pair of lists. In Haskell, zip and unzip are inverses (up to (un)currying).

In Haskell, the arguments of zip are limited to two lists. In Ruby, it's one array as receiver and one or more arrays as arguments. For transpose, it's an array of arrays. Only the later is fully generic and thus can be made exactly invertible.

Actions

Also available in: Atom PDF

Like1
Like0Like0Like0Like0Like0Like0Like0Like0