0

私は次のデータ構造を持っています:

data = [[{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
        [{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
        [{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
        [{'Posit': '0', 'R': '255', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '0', 'B': '255', 'G': '0'}],
        [{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
        [{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
        [{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}],
        [{'Posit': '0', 'R': '0', 'B': '0', 'G': '255'}, {'Posit': '1000', 'R': '255', 'B': '0', 'G': '0'}]]

上記のデータ構造で最も一般的な辞書のリストを見つけたいと思います。

私の最初のアイデアは、most_commonからの関数を使用することでしたcollections.Counterが、

from collections import Counter
c = Counter()
for point in data:
    c[point] += 1

TypeErrorリストはハッシュできないため、失敗します。

次のアイデアは、タプルは不変であるため、リストをタプルに変換することでした。

from collections import Counter
c = Counter()
for point in data:
    c[tuple(point)] += 1

TypeErrorでも、辞書もハッシュ化できないと言われました。

それで、私が望むことを達成するためのPythonicの方法は何ですか?

4

2 に答える 2

1

を使用できますCounterが、リストをタプルに変換し、辞書をタプルのソートされたタプルに変換する必要があります(2つの辞書を比較できるようにするには、タプルのソートされたタプルのキー値)。

>>> Counter(tuple(tuple(sorted(d.items())) for d in a) for a in data).most_common()

[(((('B', '0'), ('G', '255'), ('Posit', '0'), ('R', '0')),
   (('B', '0'), ('G', '0'), ('Posit', '1000'), ('R', '255'))),
  7),
 (((('B', '0'), ('G', '255'), ('Posit', '0'), ('R', '255')),
   (('B', '255'), ('G', '0'), ('Posit', '1000'), ('R', '0'))),
  1)]

@Marcinが正しくコメントtuple(sorted(d.items()))を置き換えることができるので、より適切なものに置き換えることができますfrozenset(d.items())

>>> Counter(tuple(frozenset(d.items()) for d in a) for a in data).most_common()
[((frozenset([('Posit', '0'), ('B', '0'), ('G', '255'), ('R', '0')]),
   frozenset([('R', '255'), ('G', '0'), ('B', '0'), ('Posit', '1000')])),
  7),
 ((frozenset([('Posit', '0'), ('R', '255'), ('B', '0'), ('G', '255')]),
   frozenset([('B', '255'), ('G', '0'), ('R', '0'), ('Posit', '1000')])),
  1)]
于 2012-05-03T12:46:50.283 に答える
1
from collections import namedtuple, Counter
# You can probably think of a better name than this
datum = namedtuple('datum', 'Posit R B G')
Counter(tuple(datum(**d) for d in a) for a in data).most_common()
# You might actually want to make the conversion permanent;
# the data is possibly easier to work with that way given the
# fixed key structure, and it should save memory too
于 2012-05-03T13:39:40.157 に答える