У меня есть набор кортежей: (порт, частота).

d = {(0, 410): None, (1, 640): None, (2, 88): None, (2, 410): None, (0, 33): None}

Я хочу собрать все кортежи с одинаковым номером порта, частоты для них уникальны. Затем я хочу перечислить эти частоты.

Если я могу сделать это, не имея значения, которое было бы здорово, так как оно не нужно, однако порт, freq должен быть уникальным, и создание их ключей позволило мне добиться этого.

Мне удалось перечислить все частоты, но это не то, что я хочу.

_, freq = zip (*list( d.keys() ))

Может кто-нибудь показать мне эффективный питонский способ сделать это, пожалуйста?

1
Dodomac 29 Авг 2017 в 01:45

4 ответа

Лучший ответ

Это как раз такая проблема collections.defaultdict был создан для.

Вот как вы должны создать defaultdict, который создает новый list при обращении к отсутствующему ключу:

from collections import defaultdict as ddict

dd = ddict(list)

Теперь вы можете просто заполнить ваш словарь по умолчанию вторым элементом из всех ваших кортежей:

for port, freq in d:
    dd[port].append(freq)

Выполнено. Это работает, потому что каждый раз при обращении к отсутствующему ключу со значением port создается новый list, а затем вы просто добавляете его в этот список. Если ключ уже существует, вы просто добавляете в существующий список.

Теперь вы можете получить доступ ко всем частотам для любого порта:

print(dd[0])

Примечание: если ваша цель для вашей первой структуры данных состоит в том, чтобы иметь коллекцию уникальных кортежей, вместо использования словаря для хранения ваших кортежей, я предлагаю вместо этого использовать set. set - это просто набор уникальных элементов без связанных значений, которые следует учитывать:

>>> s = {(0, 410), (1, 640), (2, 88), (2, 410), (0, 33)}
>>> type(s).__name__
'set'
1
Rick supports Monica 29 Авг 2017 в 01:22

None ценный словарь кажется неуклюжим, набор тоже работает

d = {(0, 410), (1, 640), (2, 88), (2, 410), (0, 33)}
type(d)
Out[410]: set

Itertools groupby - инструмент, если разрешены стандартные библиотеки

from itertools import groupby


grouped = [(k, *g) for k, g in groupby(sorted(list(d),
                                              key=lambda x: x[0]),
                                       key=lambda x: x[0])]
print(*grouped, sep='\n')
(0, (0, 410), (0, 33))
(1, (1, 640))
(2, (2, 88), (2, 410))

То, что я придумал, чтобы разделить структуру группы, кажется уродливым

[(b[0], list(b[-1])) 
 for b in [(a[0], *zip(*a[1:])) 
           for a in grouped ]]
Out[399]: [(0, [410, 33]), (1, [640]), (2, [88, 410])] 
1
f5r5e5d 29 Авг 2017 в 01:15

zip не является неэффективным способом сделать то, что вам нужно.
Было бы достаточно простого понимания списка:

freq = [x[1] for x in d]

Или же:

import operator as op
freq = list(map(op.itemgetter(1), d))
2
AChampion 28 Авг 2017 в 22:48

Простое решение

Давайте создадим словарь, в котором каждый ключ является портом, а каждое значение - списком частот, это позволяет вам суммировать их или работать с ними, как вам нравится, и дает вам O (1) доступ к ним!

#first let's make a dict of all the keys with empty lists
my_dict = dict.fromkeys( [str(x[0]) for x in d.keys()], [])

#now let's append those frequencies!
[my_dict[str(soc)].append(freq) for soc, freq in d.keys()]

Обратите внимание, что это не дает вам отсортированную структуру, но вы можете сохранить список сокетов и использовать его для метода from_keys и иметь отсортированный способ доступа к сокетам. например

sockets = [str(x[0]) for x in d.keys()] #str() allows us to use an integer as a key, keep this in mind!

Это, однако, делает действительно легким доступ ко всем различным частотам для данного сокета, вот так:

my_dict['socket']

Демонстрация копирования и вставки интерпретатора:

>>> d = {(0, 410): None, (1, 640): None, (2, 88): None, (2, 410): None, (0, 33): None}
>>> my_dict = dict.fromkeys( [str(x[0]) for x in d.keys()], [])
>>> [my_dict[str(soc)].append(freq) for soc, freq in d.keys()]
[None, None, None, None, None]
>>> my_dict
{'0': [410, 640, 88, 410, 33], '1': [410, 640, 88, 410, 33], '2': [410, 640, 88, 410, 33]}
>>>

Обратите внимание, что это преобразует из текущего формата, который у вас есть (или редактировать свой пост и пинг мне: D). Вы можете адаптировать любой код, который вам может понадобиться, чтобы получить аналогичные результаты и иметь равный уровень счастья для доступа к вещам. Хранение отсортированного списка ключей делает жизнь по-настоящему легкой. Предполагается, что Python3 теперь будет сохранять словари отсортированными по умолчанию, так что не поверьте мне на слово, но если вы используете my_dict.keys (), он должен вернуть их отсортированным образом, но я могу ошибаться в том, как это работает.

< Сильный > TAKEAWAY

Диктофон сокета -> частоты будет легче всего иметь дело. Дополнительный отсортированный список сокетов может также помочь

0
Erich 29 Авг 2017 в 01:31