【问题标题】:Creating a Python dictionary using a comprehension使用推导式创建 Python 字典
【发布时间】:2014-03-14 18:31:54
【问题描述】:

我正在尝试在 python 2.7.3 中创建具有以下值的 python 字典:

'A':1
'B':2
'C':3
  .
  .
  .
  .
'Z':26

使用以下任一行:

theDict = {x:y for x in map(chr,range(65,91)) for y in range(1,27)}

theDict = {x:y for x in map(chr,range(65,91)) for y in list(range(1,27))}

在这两种情况下,我得到以下结果:

'A':26
'B':26
'C':26
  .
  .
  .
  .
'Z':26

我不明白为什么第二个 for 没有生成数字 1-26。也许是这样,但如果是这样,我不明白为什么每个键的值我只能得到 26。如果我不创建字典(即只用 x 或 y 更改 x:y),x = 大写字母和 y = 1-26。

有人可以解释我做错了什么并提出一种可能的方法来获得我想要的结果。

【问题讨论】:

    标签: python dictionary list-comprehension


    【解决方案1】:

    为什么错了:你的列表理解是嵌套的。实际上是这样的:

    d = {}
    for x in map(chr, range(65, 91)):
        for y in range(1,27):
            d[x] = y
    

    如您所见,这不是您想要的。它所做的是将y 设置为1,然后遍历字母表,将所有字母设置为1,即{'A':1, 'B':1, 'C':1, ...}。然后它对 2,3,4 再次执行此操作,一直到 26。由于它是一个 dict,因此以后的设置会覆盖以前的设置,然后您就会看到结果。

    这里有几个选项,但一般来说,迭代多个伴随列表的解决方案更像是这样的模式:

    [some_expr(a,b,c) for a,b,c in zip((a,list,of,values), (b, list, of, values), (c, list, of values))]
    

    zip 从每个子列表中提取一个值,并在每次迭代中将其制成一个元组。换句话说,它将 3 个每个包含 4 个项目的列表转换为 4 个每个包含 3 个项目的列表(在上面)。在您的示例中,当您需要 26 对时,您有 26 个项目的 2 个列表; zip 会为你做到这一点。

    【讨论】:

    • 顺序是先for x...:for y...
    • 好的,我总是让它们更明确,因为我永远无法保持直截了当!
    • 感谢您的解释。我知道我错在哪里了。也感谢您让我知道 zip。
    【解决方案2】:

    试试:

    >>> {chr(k):k-64 for k in range(65,91)} 
    {'A': 1, 'C': 3, 'B': 2, 'E': 5, 'D': 4, 'G': 7, 'F': 6, 'I': 9, 'H': 8, 'K': 11, 'J': 10, 'M': 13, 'L': 12, 'O': 15, 'N': 14, 'Q': 17, 'P': 16, 'S': 19, 'R': 18, 'U': 21, 'T': 20, 'W': 23, 'V': 22, 'Y': 25, 'X': 24, 'Z': 26}
    

    或者,如果你想做你正在做的事情,请使用 zip:

    >>> {x:y for x,y in zip(map(chr,range(65,91)),range(1,27))}
    {'A': 1, 'C': 3, 'B': 2, 'E': 5, 'D': 4, 'G': 7, 'F': 6, 'I': 9, 'H': 8, 'K': 11, 'J': 10, 'M': 13, 'L': 12, 'O': 15, 'N': 14, 'Q': 17, 'P': 16, 'S': 19, 'R': 18, 'U': 21, 'T': 20, 'W': 23, 'V': 22, 'Y': 25, 'X': 24, 'Z': 26}
    

    你的不工作的原因是你的理解正在执行内部循环时间。即,在 shell 中试试这个:

    >>> [(chr(outter), inner) for outter in range(65,91) for inner in range(1,27)]
    [('A', 1), ('A', 2), ('A', 3), ('A', 4),... ('A', 26),
    ...
    ...
    ('Z', 1), ('Z', 2), ('Z', 3), ('Z', 4), ..., ('Z', 26)]
    

    如果你这样做:

    >>> len([(chr(outter), inner) for outter in range(65,91) for inner in range(1,27)])
    676
    

    可以看到它执行了 26x26 次(26x26=676)

    由于 dict 将更新为新值,因此使用每个字母的最后一个值:

    >>> dict([(chr(outter), inner) for outter in range(65,91) for inner in range(1,27)])
    {'A': 26, 'C': 26, 'B': 26, 'E': 26, 'D': 26, 'G': 26, 'F': 26, 'I': 26, 'H': 26, 'K': 26, 'J': 26, 'M': 26, 'L': 26, 'O': 26, 'N': 26, 'Q': 26, 'P': 26, 'S': 26, 'R': 26, 'U': 26, 'T': 26, 'W': 26, 'V': 26, 'Y': 26, 'X': 26, 'Z': 26}
    

    这说明了为什么你会得到你所得到的。

    【讨论】:

    • 谢谢。我更喜欢顶级方法。感谢您提供 zip。我不知道 zip。
    【解决方案3】:

    您可以尝试以下方法:

    theDict = {chr(y):y - 64 for y in range(65, 91)}
    print theDict
    

    输出:

    {'A': 1, 'C': 3, 'B': 2, 'E': 5, 'D': 4, 'G': 7, 'F': 6, 'I': 9, 'H': 8, 'K': 11, 'J': 10, 'M': 13, 'L': 12, 'O': 15, 'N': 14, 'Q': 17, 'P': 16, 'S': 19, 'R': 18, 'U': 21, 'T': 20, 'W': 23, 'V': 22, 'Y': 25, 'X': 24, 'Z': 26}
    

    【讨论】:

    • 谢谢。我更喜欢这种方法。
    • 谢谢。我喜欢这种方法。
    猜你喜欢
    • 2018-07-24
    • 2021-05-01
    • 1970-01-01
    • 2016-02-04
    • 2016-09-18
    • 2015-06-05
    • 1970-01-01
    • 2022-01-03
    • 2021-07-28
    相关资源
    最近更新 更多