如何使用 python 3 字典中的值查找键?

How to find a key using a value in a python 3 dictionary?

我正在写一个密码,我已经为字母表中的每个字母分配了数值,alphabet_dictionary = {'a': 0, 'b': 1, 'c': 2,... etc.}

我首先将 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>]'

为什么会这样?

您没有获取 letter 的内存位置,您获取的是它认为是您(无意中)创建的生成器的内存位置。 .append() 接受一个参数,当你给它一个生成器表达式时,它很乐意将其视为参数,并添加它。您可以像@Tadhg McDonald-Jensen 提到的那样将 gen-expr 包装在 next 中,或者您可以尝试将 .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.

如果您使用 nextextend,您将得到一个字母列表,这可能就是您想要的。

但很有可能,如果您想要反向映射,我也会将反向映射构建为字典。当您第一次创建 "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])
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)