2014-10-15 2 views
0

У меня есть словарь, где значения - это список не уникальных значений и связанных с различными ключами.return key under condition

mydict = {120: ["foo", "bar", "cat"], 125: ["dog", "foo", "bar"]} 

У меня есть набор значений в словаре

myset = set(['foo', 'bar', 'cat', 'dog']) 

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

120: "cat" 
125: "dog" 
125: 'foo' 
125: 'bar' 

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

result = '' 
for i in set: 
    result += "%s\t%s" % (i, [key for key in dict if i in dict[key]]) 
+0

Ваше использование 'dict' имеет неправильный синтаксис. Просто сделайте 'mydict = {120: [" foo "," bar "," cat "], 125: [" dog "," foo "," bar "]}'. –

+1

Используйте 'max ([ключ для ключа в dict, если i in dict [key]])', чтобы получить самый большой ключ? – WKPlus

+0

Работы. спасибо - я не могу поверить, что это было так просто. – oaklander114

ответ

0

Наиболее эффективное решения является первым собрать максимальный ключ за уникальное значение; вы можете предварительно фильтровать свой набор или повторно использовать результирующее сопоставление для других наборов.

Это решение O (N) (линейное время), где N - это всего Число значений в словаре. Предварительная фильтрация сводит его ниже, поскольку вы учитываете только значения в своем наборе. Сравните это с Jon's answer, который использует сортировку; алгоритм O (NlogN).

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

max_key = {} 
for key, values in mydict.iteritems(): 
    for value in values: 
     if key > max_key.get(value, float('-inf')): 
      max_key[value] = key 

result = {val: max_key[val] for val in myset} 

Вы можете использовать max_key отображение для получения результатов для любого набора в настоящее время.

Pre-фильтрации выглядит

max_key = {} 
for key, values in mydict.iteritems(): 
    for value in myset.intersection(values): 
     if key > max_key.get(value, float('-inf')): 
      max_key[value] = key 

result = {key: val for val, key in max_key.iteritems()} 

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

0

Попробуйте это:

from itertools import chain 

mydict = {120: ['foo', 'bar', 'cat'], 125: ['dog', 'foo', 'bar']} 
values = set(chain(* [v for k, v in mydict.items()])) 
# values == {'bar', 'cat', 'dog', 'foo'} 

for v in values: 
    m = 0 
    for k, vl in mydict.items(): 
     if v in vl and k > m: 
      m = k 
    print(v + " " + str(m)) 

Выход:

dog 125 
bar 125 
cat 120 
foo 125 
+0

Какова функция '*' при определении набора? – oaklander114

+0

@ oaklander114 при вызове такой функции, что '*' распаковывает следующий список. Поэтому 'foo (a, b, c)' совпадает с 'foo (* [a, b, c])' –

+0

Обратите внимание, что вы можете просто использовать: 'set(). Union (* mydict.values ​​()) 'вместо' chain'ing there (я предполагаю, что вы имели в виду 'values', а не' items' в любом случае: p) –

0

Более четкое и удобное решение, я думаю.

out = {} 

for value in myset: 
    out[val] = max([key for key, values in mydict.iteritems() if value in values]) 

выход:

{'bar': 125, 'cat': 120, 'dog': 125, 'foo': 125} 
0
if __name__ == "__main__": 
    mydict = {120: ["foo", "bar", "cat"], 125: ["dog", "foo", "bar"]} 

    tempdict = {} 
    for key, value in mydict.items(): 
     for item in value: 
      tempdict[item] = key 

    myset = set(['foo', 'bar', 'cat', 'dog']) 
    for item in myset: 
     if item in tempdict.keys(): 
      print "%d: %s" % (tempdict[item], item) 

выход:

125: foo 
125: bar 
125: dog 
120: cat 
1

Вам не нужно, чтобы построить промежуточный набор, вы можете построить генератор над dict затем сортировать элементы и использовать тот факт, что последний элемент пары ключ/значение будет наивысшей записью ключа и передать его в dict конструктор, например:

mydict = {120: ["foo", "bar", "cat"], 125: ["dog", "foo", "bar"]} 
result = dict(sorted(((v, k) for k in mydict for v in mydict[k]))) 
# {'foo': 125, 'bar': 125, 'dog': 125, 'cat': 120} 

Затем выводят result значения в зависимости от обстоятельств.


Если ты действительно хочешь фильтровать по некоторым ключевым значениям, то вы можете использовать:

required = {'cat', 'foo'} 
result = dict(sorted(((v, k) for k in mydict for v in mydict[k] if v in required))) 
# {'foo': 125, 'cat': 120}