質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2412閲覧

pythonでN個ずつ値を取り出したい。

luluca

総合スコア23

iteratorパターン

iteratorパターンとは、オブジェクト指向プログラミングのデザインパターンです。コンテナオブジェクトの要素を列挙する手段を独立させることによって、コンテナの内部仕様に依存しない反復子を提供することを目的とします。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

1クリップ

投稿2019/11/21 14:25

こんちには。

配列をグループ化して、グループを任意の単位のサブグループで括りたいと考えております。
例えば、グループ化後、2個単位にまとめる場合、以下のイメージです。

[1,1,1,2,2,3,3,4,4,4] -> [[[1,1,1],[2,2]],[[3,3],[4,4,4]]]

頑張れば、書けると思うのですが、itertoolsなどでスッキリ書きたいと思っています。
以下のように書いたのですが、なぜか奇数の時にgrouperの値が入っていないです。

python

1from itertools import groupby 2from more_itertools import chunked 3 4x = [1,1,1,2,2,3,3,4,4,4] 5x_grouped = map(lambda xx: xx[1], groupby(x)) 6for a,b in chunked(x_grouped,2): 7 print(a,b) 8 print(list(a), list(b)) 9 10## <itertools._grouper object at 0x7f24339436a0> <itertools._grouper object at 0x7f24339432e8> 11## [] [2, 2] 12## 13## <itertools._grouper object at 0x7f24339436d8> <itertools._grouper object at 0x7f24339430f0> 14## [] [4, 4, 4]

どなたか原因と解決策がお分かりの人、よろしくお願い致します。
※なんで、こんなことしたいのかは問わないでください・・

LouiS0616👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

既に解決策は出たようですが、原因がわりあい面白かったのでつらつら書きます。
簡潔に言えば、itertools.groupbyは後戻りできない仕様なのです。

Python

1import itertools 2 3g_it = itertools.groupby([1, 1, 2, 2, 3, 3]) 4 5k1, it1 = next(g_it) 6k2, it2 = next(g_it) 7print(k1, list(it1)) # => 1 [] 8print(k2, list(it2)) # => 2 [2, 2] 9 10k3, it3 = next(g_it) 11print(k3, list(it3)) # => 3 [3, 3]

Wandbox

実装上、要素を一回しか舐めないように効率化されているようです。

これは非常に嬉しい作りなのですが、
如何せんchunkedのような『先読み』を要するグルーピング関数との相性は最悪です。

返されるグループはそれ自体がイテレータで、 groupby() と iterable を共有しています。もととなる iterable を共有しているため、 groupby() オブジェクトの要素取り出しを先に進めると、それ以前の要素であるグループは見えなくなってしまいます。従って、データが後で必要な場合にはリストの形で保存しておく必要があります

引用元itertools.groupby — Python 3.8.0 ドキュメント

リンク先で紹介されている簡易実装では、is演算子がその真価を発揮しています。

解決策

前以てイテレータをリストに変換するのが最も素直でしょう。

しかし、xが非常に多い要素を持つときはメモリを圧迫する恐れもあります。
そのような事情がある際は次のようにitertools.isliceを使っても良いかもしれません。

Python

1import itertools 2 3 4x = [1, 1, 1, 2, 2, 3, 3, 4, 4, 4] 5g_it = itertools.groupby(x) 6 7n = 2 8while True: 9 elems = [list(it) for k, it in itertools.islice(g_it, 0, n)] 10 if not elems: 11 break 12 13 print(*elems)

実行結果 Wandbox

[1, 1, 1] [2, 2] [3, 3] [4, 4, 4]

投稿2019/11/21 15:43

編集2019/11/21 16:25
LouiS0616

総合スコア35658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

luluca

2019/11/21 23:20

ご丁寧にありがとうございました。 groupbyの効率化のための仕様まで理解できていなかったので勉強になりました!
guest

0

自己解決です。(勉強不足でした。)
groupby(x)の各grouperオブジェクトはイテレータにしないとダメみたいでした。
※ただ、print()の結果はよくわかっていないのですが・・

python

1x_grouped = map(lambda xx: list(xx[1]), groupby(x))

投稿2019/11/21 14:46

luluca

総合スコア23

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問