9

説明するために、2 タプルのリストから始めます。

import itertools
import operator

raw = [(1, "one"),
       (2, "two"),
       (1, "one"),
       (3, "three"),
       (2, "two")]

for key, grp in itertools.groupby(raw, key=lambda item: item[0]):
    print key, list(grp).pop()[1]

収量:

1 one
2 two
1 one
3 three
2 two

理由を調査するために:

for key, grp in itertools.groupby(raw, key=lambda item: item[0]):
    print key, list(grp)

# ---- OUTPUT ----
1 [(1, 'one')]
2 [(2, 'two')]
1 [(1, 'one')]
3 [(3, 'three')]
2 [(2, 'two')]

これでも同じ出力が得られます。

for key, grp in itertools.groupby(raw, key=operator.itemgetter(0)):
    print key, list(grp)

次のようなものを取得したい:

1 one, one
2 two, two
3 three

これは、キーがリスト内のタプル内にあるためだと考えていますが、実際にはタプルは 1 つとして移動します。目的の出力に到達する方法はありますか? たぶんgroupby()、このタスクには適していませんか?

4

3 に答える 3

13

groupby同じキーを持つ iterable の連続する要素をクラスター化します。必要な出力を生成するには、最初に並べ替えを行う必要がありますraw

for key, grp in itertools.groupby(sorted(raw), key=operator.itemgetter(0)):
    print key, map(operator.itemgetter(1), grp)

# 1 ['one', 'one']
# 2 ['two', 'two']
# 3 ['three']
于 2010-08-09T13:42:26.830 に答える
7

望ましい結果を得るためのよりクリーンな方法はこれだと思います。

>>> from collections import defaultdict
>>> d=defaultdict(list)
>>> for k,v in raw:
...  d[k].append(v)
... 
>>> for k,v in sorted(d.items()):
...  print k, v
... 
1 ['one', 'one']
2 ['two', 'two']
3 ['three']

建物dは O(n) であり、現在sorted()はデータセット全体ではなく、一意のキーの上にあります

于 2010-08-09T22:30:28.933 に答える
3

From the docs:

The operation of groupby() is similar to the uniq filter in Unix. It generates a break or new group every time the value of the key function changes (which is why it is usually necessary to have sorted the data using the same key function). That behavior differs from SQL’s GROUP BY which aggregates common elements regardless of their input order.

Since you are sorting the tuples lexicographically anyway, you can just call sorted:

for key, grp in itertools.groupby( sorted( raw ), key = operator.itemgetter( 0 ) ):
    print( key, list( map( operator.itemgetter( 1 ), list( grp ) ) ) )
于 2010-08-09T13:45:47.870 に答える