Добавить несколько значений в словарь, но избегать повторяющихся элементов в значении словаря в python - PullRequest
3 голосов
/ 30 апреля 2020

У меня есть такой список:

[('0023_RIGHT_CC', [(2574, 2798), (1324, 1545)]),
 ('0021_LEFT_CC', [(1180, 1420), (883, 1140)]),
 ('0106_LEFT_CC', [(911, 1135), (0, 86)]),
 ('0026_LEFT_CC', [(3738, 3968), (2144, 2352)]),
 ('0021_RIGHT_CC', [(2170, 2314), (1642, 1795)]),
 ('0106_LEFT_CC', [(1679, 1833), (964, 1102)]),
 ('0106_LEFT_CC', [(1091, 1198), (65, 160)]),
 ('0021_LEFT_CC', [(1180, 1420), (883, 1140)]),
 ('0021_RIGHT_CC', [(2170, 2314), (1642, 1795)]),
 ('0106_LEFT_CC', [(911, 1135), (0, 86)]),
 ('0106_LEFT_CC', [(1679, 1833), (964, 1102)]),
 ('0106_LEFT_CC', [(1091, 1198), (65, 160)]),
 ('0018_RIGHT_CC', [(1388, 1653), (1894, 2197)]),
 ('0023_RIGHT_CC', [(2574, 2798), (1324, 1545)]),
 ('0026_LEFT_CC', [(3738, 3968), (2144, 2352)])]

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

0106_LEFT_CC: [[(911, 1135), (0, 86)], [(1091, 1198), (65, 160)], [(1679, 1833), (964, 1102)]]

Обратите внимание, что повторяющиеся элементы в value из словаря следует избегать. Я сделал следующее:

from collections import defaultdict

d = defaultdict(list)
for key, value in data:
    d[key].append(value)

и получил следующий результат.

defaultdict(list,
            {'0023_RIGHT_CC': [[(2574, 2798), (1324, 1545)],
              [(2574, 2798), (1324, 1545)]],
             '0021_LEFT_CC': [[(1180, 1420), (883, 1140)],
              [(1180, 1420), (883, 1140)]],
             '0106_LEFT_CC': [[(911, 1135), (0, 86)],
              [(1679, 1833), (964, 1102)],
              [(1091, 1198), (65, 160)],
              [(911, 1135), (0, 86)],
              [(1679, 1833), (964, 1102)],
              [(1091, 1198), (65, 160)]],
             '0026_LEFT_CC': [[(3738, 3968), (2144, 2352)],
              [(3738, 3968), (2144, 2352)]],
             '0021_RIGHT_CC': [[(2170, 2314), (1642, 1795)],
              [(2170, 2314), (1642, 1795)]],
             '0018_RIGHT_CC': [[(1388, 1653), (1894, 2197)]]})

Но результат показывает, например, что в key 0106_LEFT_CC некоторые values повторяются. Как этого избежать.

Ответы [ 2 ]

4 голосов
/ 30 апреля 2020

Вы можете преобразовать их в set, а затем снова в list. Это избавит вас от повторяющихся элементов.

from collections import defaultdict

data = [('0023_RIGHT_CC', [(2574, 2798), (1324, 1545)]),
 ('0021_LEFT_CC', [(1180, 1420), (883, 1140)]),
 ('0106_LEFT_CC', [(911, 1135), (0, 86)]),
 ('0026_LEFT_CC', [(3738, 3968), (2144, 2352)]),
 ('0021_RIGHT_CC', [(2170, 2314), (1642, 1795)]),
 ('0106_LEFT_CC', [(1679, 1833), (964, 1102)]),
 ('0106_LEFT_CC', [(1091, 1198), (65, 160)]),
 ('0021_LEFT_CC', [(1180, 1420), (883, 1140)]),
 ('0021_RIGHT_CC', [(2170, 2314), (1642, 1795)]),
 ('0106_LEFT_CC', [(911, 1135), (0, 86)]),
 ('0106_LEFT_CC', [(1679, 1833), (964, 1102)]),
 ('0106_LEFT_CC', [(1091, 1198), (65, 160)]),
 ('0018_RIGHT_CC', [(1388, 1653), (1894, 2197)]),
 ('0023_RIGHT_CC', [(2574, 2798), (1324, 1545)]),
 ('0026_LEFT_CC', [(3738, 3968), (2144, 2352)])]

d = defaultdict(list)
for key, value in data:
    d[key] = list(set(d[key] + value))


EDIT : я немного изменил ответ @ JST99 и теперь он использует set для проверок in , а затем добавляет значение в список. Это быстрее для больших наборов данных, но для ваших текущих данных ответ @ JST99 быстрее.

from collections import defaultdict


data = [('0023_RIGHT_CC', [(2574, 2798), (1324, 1545)]),
 ('0021_LEFT_CC', [(1180, 1420), (883, 1140)]),
 ('0106_LEFT_CC', [(911, 1135), (0, 86)]),
 ('0026_LEFT_CC', [(3738, 3968), (2144, 2352)]),
 ('0021_RIGHT_CC', [(2170, 2314), (1642, 1795)]),
 ('0106_LEFT_CC', [(1679, 1833), (964, 1102)]),
 ('0106_LEFT_CC', [(1091, 1198), (65, 160)]),
 ('0021_LEFT_CC', [(1180, 1420), (883, 1140)]),
 ('0021_RIGHT_CC', [(2170, 2314), (1642, 1795)]),
 ('0106_LEFT_CC', [(911, 1135), (0, 86)]),
 ('0106_LEFT_CC', [(1679, 1833), (964, 1102)]),
 ('0106_LEFT_CC', [(1091, 1198), (65, 160)]),
 ('0018_RIGHT_CC', [(1388, 1653), (1894, 2197)]),
 ('0023_RIGHT_CC', [(2574, 2798), (1324, 1545)]),
 ('0026_LEFT_CC', [(3738, 3968), (2144, 2352)])]


d = defaultdict(list)
s = defaultdict(set)
for key, value in data:
    s_value = tuple(value) # lists are unhasable, so we will use tuple
    if s_value not in s[key]: 
        d[key].append(value)
        s[key].add(s_value)

del s # we dont need s anymore
3 голосов
/ 30 апреля 2020

@ Ekrem DİNÇEL уже предоставила полнофункциональное решение, которое заслуживает выбора. Тем не менее, исключительно для справочных целей OP, я публикую альтернативное решение, которое позволяет избежать повторного приведения от list до set, и наоборот.

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

d = defaultdict(set)

for key, values in data:
    for value in values:
        d[key].add(value)

Результат:

{'0023_RIGHT_CC': {(1324, 1545), (2574, 2798)}, '0021_LEFT_CC': {(1180, 1420), (883, 1140)}, '0106_LEFT_CC': {(0, 86), (964, 1102), (1679, 1833), (65, 160), (911, 1135), (1091, 1198)}, '0026_LEFT_CC': {(3738, 3968), (2144, 2352)}, '0021_RIGHT_CC': {(1642, 1795), (2170, 2314)}, '0018_RIGHT_CC': {(1388, 1653), (1894, 2197)}}

РЕДАКТИРОВАТЬ

Эта реализация проверяет, существует ли дублирующее значение во вложенном списке, и добавляет значение, только если оно не является дубликатом. Таким образом, мы можем сохранить структуру данных кортежа, как указано. Однако обратите внимание, что эта реализация немного неэффективна из-за того, что операция in занимает линейное время на list (в отличие от постоянного времени на set).

d = defaultdict(list)

for key, value in data:
    if value not in d[key]:
        d[key].append(value)

Результат:

{'0023_RIGHT_CC': [[(2574, 2798), (1324, 1545)]], '0021_LEFT_CC': [[(1180, 1420), (883, 1140)]], '0106_LEFT_CC': [[(911, 1135), (0, 86)], [(1679, 1833), (964, 1102)], [(1091, 1198), (65, 160)]], '0026_LEFT_CC': [[(3738, 3968), (2144, 2352)]], '0021_RIGHT_CC': [[(2170, 2314), (1642, 1795)]], '0018_RIGHT_CC': [[(1388, 1653), (1894, 2197)]]}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...