2016-03-31 3 views
1

Я пишу шифр, и я присвоил числовые значения каждой букве в алфавите, alphabet_dictionary = {'a': 0, 'b': 1, 'c': 2,... etc.}.Как найти ключ, используя значение в словаре python 3?

Я сначала конвертирую письмо в message в номера, выполняю некоторую арифметику и сохраняю эти числа в переменной с именем code.

Я хочу преобразовать их обратно в письма.

До сих пор у меня есть:

for number in code: 
    for letter, value in alphabet_dictionary.items(): 
     if value == number: 
      coded_message.append(letter) 

Это работает. В итоге я получил правильное кодированное сообщение внутри моего списка coded_message. Есть ли что-то лучшее или более эффективное?

Почему я не могу сделать это в одной строке? Я первый попытался с помощью:

for number in code: 
    coded_message.append(letter for letter, value in alphabet_dictionary.items() if value == number) 

но добавляет только адреса выделения памяти для отдельных символов, например:

`[<generator object <genexpr> at 0x1011bb240>, <generator object <genexpr> at 0x1011bb1f8>, <generator object <genexpr> at 0x1011bb288>, <generator object <genexpr> at 0x1011bb2d0>, <generator object <genexpr> at 0x1011bb318>, <generator object <genexpr> at 0x1011bb360>, <generator object <genexpr> at 0x1011bb3a8>]' 

Почему это происходит?

+1

Возможный дубликат [обратного поиска словаря - Python] (http://stackoverflow.com/questions/25 68673/inverse-dictionary-lookup-python) –

+0

, если вы абсолютно уверены, что будет только одно совпадение с значением, которое вы можете использовать 'coded_message.append (next (letter for letter, value in alphabet_dictionary.items(), если значение == number)) ', чтобы получить следующее (первое) значение выражения генератора, но в качестве принятого ответа [Обратный поиск слова - Python] (http : //stackoverflow.com/questions/2568673/inverse-dictionary-lookup-python) указывает: нет гарантии наследования, что значение присутствует в словаре. –

+0

Поскольку вы просто связываете буквы с числами, вы можете просто использовать 'string.ascii_lowercase [index]' для поиска буквы по индексу и 'string.ascii_lowercase.index (char)' для получения индекса символа. –

ответ

1

Вы не получаете ячейки памяти для letter, вы получаете ячейки памяти для того, что, по его мнению, является генераторами, которые вы (непреднамеренно) создаете. .append() принимает один аргумент, и когда вы даете ему генератор-expr, он с радостью рассматривает это как аргумент и добавляет его. Вы можете либо обернуть GEN-выраж в next, как упоминает @Tadhg McDonald-Jensen, или вы можете попытаться изменить .append() к .extend()

Выработать немного:

x = letter for letter, value in alphabet_dictionary.items() if value == number 
type(x) ## generator-expression 
for i in x: 
    print(i) 
## will only print the single value that satisfied this generator 

Точно так же, если вы сделали это явное список понимание внутри .append(), он может более легко показать проблему:

for number in code: 
    coded_message.append([letter for letter, value in alphabet_dictionary.items() if value == number]) 

coded_message 
## [["a"], ["b"],... ] - not the right order, of course, but now you have a list of lists, which is probably not what you want. 

Если вы используете либо next или extend, вы получите список писем, которые, вероятно, вы хотите.

По всей вероятности, если вы хотите обратное сопоставление, я бы построил обратное отображение как словарь. Когда вы сначала создаете свое сопоставление, например, «a» = 0, также создавайте словарь с 0 = «a». Это будет быстрее для просмотровых (хотя и с алфавитным списком размером, вы, вероятно, не заметите), и позволит вам сделать проверку вменяемость, такими как

for letter, number in alphabet_dict.items(): 
    if number_dict[number] != letter: 
     raise "Something got confused: got {}->{}->{}".format(letter, number, number_dict[number]) 
0
import string 
#this builds a similar dictionary to yours: 
alphabet_dictionary = {a:ord(a)-ord('a') for a in string.ascii_lowercase} 

Вы можете использовать map:

code = 'somestring' 
coded_message = map(alphabet_dictionary.__getitem__, code) 

Для декодирования:

#invert the dictionary, in your case it's easy because it's 1-to-1: 
decode_dictionary = {v:k for k,v in alphabet_dictionary.items()} 
decoded_message = map(decode_dictionary.__getitem__, coded_message) 
Смежные вопросы