Python 列表和生成

发布于 2024-11-18 21:17:22 字数 1360 浏览 3 评论 0原文

我对 Project Euler 问题 24 有以下(正确的)解决方案。我对 Python 比较陌生,并且被几个 Python 点所困扰。

首先是代码:

# A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4.
# If all of the permutations are listed numerically or alphabetically, we call it lexicographic order.
# The lexicographic permutations of 0, 1 and 2 are: 012 021 102 120 201 210
# What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

permutations = []

def getLexicographicPermutationsOf(digits, state):
    if len(digits) == 0:
        permutations.append(str(state))

    for i in range(len(digits)):
        state.append(digits[i])
        rest = digits[:i] + digits[i+1:]
        getLexicographicPermutationsOf(rest, state)
        state.pop()

digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
getLexicographicPermutationsOf(digits, [])
print(permutations[999999])

我的第一个查询是关于yield 语句的使用。我的第一个设计不是在顶部定义排列列表,而是用 yield state 替换 permutations.append 行。然后我将该方法的返回值分配给一个变量。我查了一下,返回值是一个生成器,正如预期的那样。然而,循环其内容表明没有生成任何值。我在这里错过了什么吗?

我的第二个查询是关于最后一行 - 打印列表中的值。当我运行它时,它输出的值就好像它是一个列表,而它应该是一个字符串。事实上,将 print(permutations[999999]) 替换为 print(type(permutations[999999])) 会导致 <类str>。那么为什么它像列表一样打印(带有方括号,用逗号分隔)?

I have the following (correct) solution to Project Euler problem 24. I'm relatively new to Python, and am stumped on a couple of Python points.

First, the code:

# A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4.
# If all of the permutations are listed numerically or alphabetically, we call it lexicographic order.
# The lexicographic permutations of 0, 1 and 2 are: 012 021 102 120 201 210
# What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

permutations = []

def getLexicographicPermutationsOf(digits, state):
    if len(digits) == 0:
        permutations.append(str(state))

    for i in range(len(digits)):
        state.append(digits[i])
        rest = digits[:i] + digits[i+1:]
        getLexicographicPermutationsOf(rest, state)
        state.pop()

digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
getLexicographicPermutationsOf(digits, [])
print(permutations[999999])

My first query is regarding the use of the yield statement. Instead of defining the permutations list at the top, my first design was to replace the permutations.append line with yield state. I would then assign the return value of the method to a variable. I checked, and the return value was a generator, as expected. However, looping over its contents indicated that no values were being generated. Am I missing something here?

My second query is about the final line - printing a value from the list. When I run this, it outputs the values as though it was a list, whereas it should be a string. In fact, replacing print(permutations[999999]) with print(type(permutations[999999])) results in < class str>. So why is it being printed like a list (with square brackets, separated by commas)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

醉南桥 2024-11-25 21:17:22

当您递归调用 getLexicgraphicPermutationsOf 时,您也需要从那里产生结果。

for result in getLexicographicPermutationsOf(rest, state):
    yield result

permutations.append(str(state)) 创建 state 的字符串表示形式,它是一个列表。这解释了为什么它在打印时看起来像一个列表。

When you recursively call getLexicographicPermutationsOf, you need to yield results from there too.

for result in getLexicographicPermutationsOf(rest, state):
    yield result

permutations.append(str(state)) creates a string representation of state, which is a list. This explains why it looks like a list when printed.

丶情人眼里出诗心の 2024-11-25 21:17:22

有一种计算强度较小的方法来计算此值。编写程序实际上可能并不那么容易,但它可以让您手动计算出答案。 :) (提示:有多少种排列?其中有多少是从 0 开始的?)

此外,range(len(x)) 非常不符合 Python 风格。当然,最好有索引来对列表进行切片以删除“当前”元素...但是还有另一种方法:只需要求 Python 删除具有该值的元素(因为只有一个这样的元素)。这允许我们直接循环元素值:

for digit in digits:
    state.append(digit)
    rest = digits[:]
    rest.remove(digit) # a copy with the current value removed.
    getLexicographicPermutationsOf(rest, state)
    state.pop()

range 主要用于实际创建数据范围 - 例如初始化digits。 :)

我在这里遗漏了什么吗?

您错过了仅递归调用函数不会神奇地将其结果放在任何地方。事实上,即使你“产生”递归调用的结果,它仍然不会做你想做的事 - 你最终会得到一个返回生成器的生成器(返回生成器等......直到当您需要一个生成器时,递归的基础)。 (FogleBird 的答案解释了如何处理这个问题:您必须从递归调用中获取生成器,并显式地将其生成的元素“馈送到”当前生成器中。)

但无论如何,还有一种更简单的方法:库已经构建了此算法 整个程序

可以这样完成:

from itertools import permutations, islice
print next(islice(permutations(range(10)), 1000000, None))

为什么它像列表一样打印(带有方括号,用逗号分隔)?

因为字符串中包含方括号和逗号。这就是在列表(在本例中为 state)上使用 str 时得到的结果。

There is a much less computationally intensive way to calculate this. It might actually not be so easy to write a program, but it lets you work out the answer by hand. :) (Hint: how many permutations are there? How many of them start with 0?)

Also, range(len(x)) is highly un-Pythonic. Granted, it would be nice to have the indices in order to slice the list to remove the 'current' element... but there is another way: just ask Python to remove the elements with that value (since there is only one such element). That allows us to loop over element values directly:

for digit in digits:
    state.append(digit)
    rest = digits[:]
    rest.remove(digit) # a copy with the current value removed.
    getLexicographicPermutationsOf(rest, state)
    state.pop()

range is primarily useful for actually creating data ranges - such as you initialize digits with. :)

Am I missing something here?

You're missing that just calling a function recursively won't magically put its results anywhere. In fact, even if you 'yield' the results of a recursive call, it still won't do what you want - you'll end up with a generator that returns generators (that return generators, etc.... down to the base of the recursion) when you want one generator. (FogleBird's answer explains how to deal with this: you must take the generator from the recursive call, and explicitly "feed" its yielded elements into the current generator.)

But there is a much simpler way anyway: the library already has this algorithm built in.

The entire program can be done thus:

from itertools import permutations, islice
print next(islice(permutations(range(10)), 1000000, None))

why is it being printed like a list (with square brackets, separated by commas)?

Because the string contains square brackets and commas. That's what you get when you use str on a list (state, in this case).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文