Как создать словарь для обратного просмотра элементов списка, каждый из которых имеет наборы? - PullRequest
1 голос
/ 28 марта 2019

У меня есть имена тестов в списке, подобном этому в Python v2.7:

all_tests = ['test1', 'test2', 'test3', ..., 'testN']

И для каждого имени теста я могу найти набор свойств, которые имеет тест:

series['test'] = {'prop1', 'prop2', 'prop3', ..., 'propN'}

Например,

series['test1'] = {'yellow', 'blue', 'orange'}
series['test2'] = {'blue', 'red', 'black'}
series['test3'] = {'yellow', 'green', 'black'}

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

Так что для приведенного выше примератри теста, я хотел бы создать этот словарь:

result = {
          'yellow': {'test1', 'test3'},
          'blue':   {'test1', 'test2'},
          'orange': {'test1'},
          'red':    {'test2'},
          'black':  {'test2', 'test3'}
          'green':  {'test3'}
}

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

tuple( series[test], test ) for test in all_tests

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

Ответы [ 4 ]

2 голосов
/ 28 марта 2019

Простое решение с циклическим использованием collections.defaultdict

from collections import defaultdict
d = defaultdict(set)
for k,v in series.items():
    for prop in v:
        d[prop].add(k)
print(d)
#defaultdict(set,
#            {'black': {'test2', 'test3'},
#             'blue': {'test1', 'test2'},
#             'green': {'test3'},
#             'orange': {'test1'},
#             'red': {'test2'},
#             'yellow': {'test1', 'test3'}})

Другой подход с использованием pandas

Первое преобразование series в DataFrame:

import pandas as pd
df = pd.DataFrame({k: list(v) for k, v in series.items()})
print(df)
#    test1  test2   test3
#0    blue   blue   black
#1  orange  black   green
#2  yellow    red  yellow

Далее melt DataFrame, groupby value и использование set в качестве функции агрегирования:

print(pd.melt(df).groupby("value", as_index=True).agg(set))
#              variable
#value                 
#black   {test3, test2}
#blue    {test1, test2}
#green          {test3}
#orange         {test1}
#red            {test2}
#yellow  {test1, test3}

Наконец, чтобы вернуться к словарю,вызовите to_records() и примените конструктор dict:

print(dict(pd.melt(df).groupby("value", as_index=True).agg(set).to_records()))
#{'black': {'test2', 'test3'},
# 'blue': {'test1', 'test2'},
# 'green': {'test3'},
# 'orange': {'test1'},
# 'red': {'test2'},
# 'yellow': {'test1', 'test3'}}
1 голос
/ 28 марта 2019

Вот альтернатива, которая создает обычный словарь:

series = {
    'test1': {'yellow', 'blue', 'orange'},
    'test2': {'blue', 'red', 'black'},
    'test3': {'yellow', 'green', 'black'},
}

result = {}
for name, props in series.items():
    for prop in props:
        result.setdefault(prop, set()).add(name)

from pprint import pprint
pprint(result)

Вывод:

{'black': set(['test2', 'test3']),
 'blue': set(['test1', 'test2']),
 'green': set(['test3']),
 'orange': set(['test1']),
 'red': set(['test2']),
 'yellow': set(['test1', 'test3'])}

Другая альтернатива для получения того же результата:

from itertools import chain

properties = set(chain.from_iterable(series.values()))  # All possible.
result = {prop: {name for name, props in series.items() if prop in props}
                    for prop in properties}

from pprint import pprint
pprint(result)
0 голосов
/ 28 марта 2019

Создайте набор из всех доступных цветов.Затем для каждого цвета создайте набор записей серии, содержащих этот цвет:

colors = set( color for colors in series.values() for color in colors ) 
result = { color:set(test for test in series if color in series[test]) for color in colors }
print(result)
# {'green': {'test3'}, 'red': {'test2'}, 'black': {'test2', 'test3'}, 'yellow': {'test1', 'test3'}, 'orange': {'test1'}, 'blue': {'test1', 'test2'}}
0 голосов
/ 28 марта 2019

У вас уже есть набор или итерация, содержащая все свойства, например, all_props
Тогда ваш обратный дикт может быть создан с помощью

rev_series = {p: {k for k, v in series.items() if p in v} for p in all_props}

Если нет:

all_props = set()
for s in series.values():
    all_props = all_props.union(s)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...