Как сделать элемент кортежа уникальным? - PullRequest
4 голосов
/ 08 сентября 2010

у меня есть кортеж словарей результатов.

result = ({'name': 'xxx', 'score': 120L }, {'name': 'xxx', 'score': 100L}, {'name': 'yyy', 'score': 10L})

Я хочу удалить его.После операции uniqify result = ({'name': 'xxx', 'score': 120L }, {'name': 'yyy', 'score': 10L})

result содержит только one dictionary каждого name, а dict должно иметь maximum score.Окончательный результат должен быть в том же формате, то есть кортеж словаря.

Ответы [ 4 ]

2 голосов
/ 08 сентября 2010

Я бы создал промежуточный словарь, сопоставляющий каждое имя с максимальной оценкой для этого имени, а затем снова превратил бы его в набор слов:

>>> result = ({'name': 'xxx', 'score': 120L }, {'name': 'xxx', 'score': 100L}, {'name': 'xxx', 'score': 10L}, {'name':'yyy', 'score':20})
>>> from collections import defaultdict
>>> max_scores = defaultdict(int)
>>> for d in result: 
...     max_scores[d['name']] = max(d['score'], max_scores[d['name']])
... 
>>> max_scores 
defaultdict(<type 'int'>, {'xxx': 120L, 'yyy': 20})
>>> tuple({name: score} for (name, score) in max_scores.iteritems()) 
({'xxx': 120L}, {'yyy': 20})

Примечания: 1) Я добавил {'name': 'yyy', 'score': 20} к вашему примеру данных, чтобы показать, что он работает с кортежем с более чем одним именем.

2) Я использую defaultdict, который предполагает, что минимальное значение для оценки равно нулю. Если оценка может быть отрицательной, вам нужно изменить параметр int в defaultdict (int) на функцию, которая возвращает число, меньшее минимально возможного значения.

Между прочим, я подозреваю, что наличие набора словарей - не лучшая структура данных для того, что вы хотите сделать. Рассматривали ли вы альтернативы, такие как наличие единственного диктанта, возможно, со списком баллов для каждого имени?

2 голосов
/ 08 сентября 2010
from operator import itemgetter

names = set(d['name'] for d in result)
uniq = []
for name in names:
    scores = [res for res in result if res['name'] == name]
    uniq.append(max(scores, key=itemgetter('score')))

Я уверен, что есть более короткое решение, но вы не сможете сначала избежать фильтрации оценок по имени, а затем найти максимум для каждого имени.

Хранение партитур в словаре с именами в качестве ключей здесь определенно предпочтительнее.

1 голос
/ 08 сентября 2010

Я бы пересмотрел структуру данных, чтобы лучше соответствовать вашим потребностям (например, dict хэшируется с именем со списком баллов в качестве значения), но я бы сделал так:

import operator as op
import itertools as it

result = ({'name': 'xxx', 'score': 120L },
          {'name': 'xxx', 'score': 100L},
          {'name': 'xxx', 'score': 10L},
          {'name':'yyy', 'score':20})
# groupby

highscores = tuple(max(namegroup, key=op.itemgetter('score'))
                   for name,namegroup in it.groupby(result,
                                                    key=op.itemgetter('name'))
                   )
print highscores
0 голосов
/ 08 сентября 2010

Как насчет ...

inp  = ({'name': 'xxx', 'score': 120L }, {'name': 'xxx', 'score': 100L}, {'name': 'yyy', 'score': 10L})

temp = {}
for dct in inp:
    if dct['score'] > temp.get(dct['name']): temp[dct['name']] = dct['score']

result = tuple({'name': name, 'score': score} for name, score in temp.iteritems())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...