【问题标题】:can someone explain the following list comprehension有人可以解释以下列表理解吗
【发布时间】:2013-01-22 22:35:56
【问题描述】:

这是 python 文档中关于如何生成随机序列的简单代码,即当每个序列都有关联的权重时选择颜色。

我理解这个概念,但是当我尝试自己做时,我无法弄清楚列表理解在做什么。有人可以反复解释这个列表理解在做什么,这样我就可以更好地理解这段代码。谢谢。

weighted_choices = [('Red', 3), ('Blue', 2), ('Yellow', 1), ('Green', 4)]
population = [val for val, cnt in weighted_choices for i in range(cnt)]
random.choice(population)
'Green'

【问题讨论】:

  • 嵌套列表推导的经验法则:按照它们在推导中出现的顺序展开 for 循环。
  • 作为说明,我认为这不是进行加权随机选择的好方法。

标签: python list list-comprehension


【解决方案1】:
weighted_choices = [('Red', 3), ('Blue', 2), ('Yellow', 1), ('Green', 4)]
population = [val for val, cnt in weighted_choices for i in range(cnt)]
random.choice(population)
'Green'

让理解开始变得简单

simple = [val for val, cnt in weighted_choices]

这个简单的列表理解是这样做的:

  • 对于 weighted_choices 中的每个项目,打破第一部分并将其分配给 val,将第二部分分配给 cnt。
  • 取出 val 并从每个 val 中创建一个新数组

这会产生:

['Red','Blue','Yellow''Green']

现在让我们看看第二部分,让我们先做一个简单的列表理解

second_part = ['Red' for i in range(3)]

列表理解的第二部分是这样做的:

  • 对于 range(3) 中的每个 i(数字 [0,1,2])
  • 丢弃 i 并将“红色”添加到列表中

这会产生:

['Red','Red','Red']

结合两种理解:

population = [val for val, cnt in weighted_choices for i in range(cnt)]

这个简单的列表理解是这样做的:

  • 对于 weighted_choices 中的每个项目,将第一部分拆分并将其分配给 val,将第二部分分配给 cnt。 (例如,“红色”和第一项为 3)
  • 取 val 和
  • 对于 range(cnt) 中的每个 i(如果 cnt 为 3,则数字 [0,1,2])丢弃 i 并将 val 添加到列表中

这会产生:

['Red', 'Red', 'Red', 'Blue', 'Blue', 'Yellow', 'Green', 'Green', 'Green', 'Green']

【讨论】:

    【解决方案2】:

    把它想象成一个看起来像这样的for 循环:

    population = []
    for val, cnt in weighted_choices:
      for i in range(cnt):
        population.append(val)
    

    weighted_choices 开始,它遍历每个项目,为您提供如下内容:

    ('Red', 3)
    

    从那里开始,它遍历cnt(此处为3)的长度范围,并将val(红色)多次附加到population。所以最后你得到:

    ['Red',
     'Red',
     'Red',
     'Blue',
     'Blue',
     'Yellow',
     'Green',
     'Green',
     'Green',
     'Green']
    

    如您所见,其中包含三次Red、两次Blue、一次Yellow和四次Green,这反映了初始列表中每种颜色旁边的数字。

    当我查看像这样双重嵌套的列表推导时,我只是想到了一个像上面那样的 for 循环,然后在我的脑海中“压扁”它,这样它就在一条线上。不是最先进的方法,但它可以帮助我保持直截了当:)

    【讨论】:

      【解决方案3】:

      最好展开列表推导分析:

      population = []
      for val, cnt in weighted_choices:
          for i in range(cnt):
              population.append(val)
      

      这会将weighted_choices 扩展为一个元素列表,其中每个项目根据其权重重复; Red 加了 3 次,Blue 加了 2 次,以此类推:

      ['Red', 'Red', 'Red', 'Blue', 'Blue', 'Yellow', 'Green', 'Green', 'Green', 'Green']
      

      random.choice() 函数然后随机获取其中一个元素,但 Green 出现 4 次,因此比 Yellow 更有可能被选中,Yellow 在扩展列表中仅出现一次.

      【讨论】:

        【解决方案4】:

        列表理解由 2 个 for 循环组成。

        改用print 试试

        for val, cnt in weighted_choices:
          # the first for loop will be executed len(weighted_choices) times = 4
          for i in range(cnt):
          # the second for loop will be executed cnt times
          # for each execution of the outer loop 
          # (cnt = second element of each tuple)
              print val # it will print each first element of the tuple 'Red', ...
                        # len(weighted_choices) * cnt times
        

        现在,您的代码将 val 添加到名为 population 的列表中,而不是 print。 其余的很简单,代码使用列表作为输入进行随机选择。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-05-27
          • 2011-11-22
          • 2016-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多