【问题标题】:Understanding Specific Python List Comprehension了解特定的 Python 列表理解
【发布时间】:2019-06-20 20:09:39
【问题描述】:

在给定骰子数量和面数的情况下,我正在尝试使用此代码产生掷骰子的所有可能结果。此代码有效(但我不太明白列表理解是如何工作的。

def dice_rolls(dice, sides):
   """
   Equivalent to list(itertools.product(range(1,7), repeat=n)) except
   for returning a list of lists instead of a list of tuples.
   """
   result = [[]]
   print([range(1, sides + 1)] * dice)
   for pool in [range(1, sides + 1)] * dice:
      result = [x + [y] for x in result for y in pool]
   return result

因此,我正在尝试重写列表理解

result = [x + [y] for x in result for y in pool]

进入 FOR 循环以尝试了解其工作原理,但目前无法正确执行。当前失败代码:

for x in result:
   for y in pool:
      result = [x + [y]]

第二个问题:如果我想把它变成一个生成器(因为如果你有足够的骰子和边,这个函数是一个内存猪),我是否只是简单地产生列表中的每个项目,而不是抛出进入结果列表?

编辑:我想出了一种方法,在得到很好的响应后将列表理解分解为循环并想要捕获它:

def dice_rolls(dice, sides):
result = [[]]
for pool in [range(1, sides + 1)] * dice:
    temp_result = []
    for existing_values in result:  # existing_value same as x in list comp.
        for new_values in pool:  # new_value same as y in list comp.
            temp_result.append(existing_values + [new_values])
    result = temp_result
return result

【问题讨论】:

  • 如果你有足够的骰子和边数让这个函数成为内存问题,那么即使使用生成器,你也会遇到时间问题。您需要以一种不涉及枚举所有抛出结果的方式来解决您的潜在问题。
  • 嗯,那就用itertools.product吧?
  • 另外,是的,文档字符串甚至提到了itertools.product
  • 我知道我可以只使用 itertools.product,这就是为什么我将它留在发布的代码中,但我正试图围绕这个特定的列表理解。

标签: python python-3.x generator list-comprehension


【解决方案1】:

我对这个问题(以及一般的列表推导)的第一直觉是使用递归。尽管您已经要求 LOOPS,但这是非常具有挑战性的。

这是我想出来的;

def dice_rollsj(dice, sides):
    result = [[]]

    for num_dice in range(dice):
        temp_result = []
        for possible_new_values in range(1, sides+1):
            for existing_values in result:
                new_tuple = existing_values + [possible_new_values]
                temp_result.append(new_tuple)
        result = temp_result

我认为您会得到相同的正确答案,但数字的顺序会有所不同。这可能是由于将值附加到列表的方式。我不知道......如果这有帮助,请告诉我。

我尝试添加尽可能多的行,因为目标是扩展和理解理解。

【讨论】:

  • 您的回答非常好。我重写了您的代码以使用原始的 for 循环,但您的代码更清晰一些,因为它将 for pool in [range(1, sides + 1)] * dice: 拆分为两个循环,但我想看看它包含的样子。我发现如果你把它分成循环,你需要第二个temp_result
  • 是的,我把它贴在原始帖子的顶部(在编辑下)。不知道如何发布子cmets中的所有代码。
【解决方案2】:

您正在通过for y in pool 循环的每次迭代重新定义结果。我相信您想要的是附加结果:

result = []
for x in result:
   for y in pool:
      result.append(x + [y])

【讨论】:

  • 除非您需要避免在 循环之后踩踏 result 变量。
  • 我猜列表理解中令我困惑的部分是:for x in result。对于第一个循环,result 中没有任何内容,而是一个空列表,因此它将 [y] 添加到一个空列表中。但最终产品不再包含空列表?
  • [] + [y] -> [y]
  • 现在确实更有意义了,我仍然想在传统的 FOR 循环中重写它以帮助理解。仍在关闭。
猜你喜欢
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-03
  • 2021-04-07
  • 1970-01-01
相关资源
最近更新 更多