如何使用 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.
如果您使用 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])
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)
我正在写一个密码,我已经为字母表中的每个字母分配了数值,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.
如果您使用 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])
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)