for each loop python – 嵌套循环

huangapple go评论70阅读模式
英文:

for each loop pyton - nested loop

问题

lyrics = ["我想要自由", "我想要自由", "我想要自由", "是的,我想要自由"]
number_of_lines = 6
for line in lyrics:
   print(line)
英文:
lyrics = ["I want to break free", "I want to break free",
          "I want to break free", "yes, I want to break free"]
number_of_lines = 6

I am trying to create a loop that prints as many lines as many number_of_lines. In this specific example I basically need to loop IN lyrics 1.5 times to print the whole list (4 lines) and then the first 2 again to get to 6 = number of lines. How do you do it exactly?

thanks much in advance

for line in lyrics:
   print(line)

答案1

得分: 1

使用itertools.cycle来重复列表的内容,直到获得所需数量的行数(使用itertools.islice):

from itertools import cycle, islice

lyrics = ["I want to break free", "I want to break free",
          "I want to break free", "yes, I want to break free"]
number_of_lines = 6

for line in islice(cycle(lyrics), 6):
    print(line)

这会增加一些额外的内存开销。cycle必须缓存它从迭代器中读取的值以便重复使用。当使用cycle和大型列表时需要考虑这一点,但通常列表会很小。

问题在于cycle会迭代其可迭代参数从中获取的迭代器,而迭代器背后的列表在调用next之间可能会发生变化。例如:

from itertools import cycle
x = [1,2,3]
i = cycle(x)
next(i)  # 输出 1
next(i)  # 输出 2
x.clear()
next(i)  # 不是3,输出 1
next(i)  # 输出 2
next(i)  # 输出 1
英文:

Use itertools.cycle to repeat the contents of the list as often as necessary to obtain the desired number of lines (using itertools.islice):

from itertools import cycle, islice


lyrics = ["I want to break free", "I want to break free",
          "I want to break free", "yes, I want to break free"]
number_of_lines = 6

for line in islice(cycle(lyrics), 6):
    print(line)

This incurs some additional memory overhead, though. cycle has to cache the values it reads from its iterator in order to repeat them. Just something to keep in mind when using cycle and large lists, but typically the lists will be small.

The issue is that cycle iterates over an iterator it obtains from its iterable argument, and the list behind the iterator could change between calls to next. For example,

>>> from itertools import cycle
>>> x = [1,2,3]
>>> i = cycle(x)
>>> next(i)
1
>>> next(i)
2
>>> x.clear()
>>> next(i)  # Not 3
1
>>> next(i)
2
>>> next(i)
1

答案2

得分: 0

你可以使用模运算符如下所示:

lyrics = ["我想要自由", "我想要自由", "我想要自由", "是的,我想要自由"]
number_of_lines = 6

for i in range(number_of_lines):
    print(lyrics[i%len(lyrics)])

输出:

我想要自由
我想要自由
我想要自由
是的,我想要自由
我想要自由
我想要自由
英文:

You could use the modulo operator as follows:

lyrics = ["I want to break free", "I want to break free", "I want to break free", "yes, I want to break free"]
number_of_lines = 6

for i in range(number_of_lines):
    print(lyrics[i%len(lyrics)])

Output:

I want to break free
I want to break free
I want to break free
yes, I want to break free
I want to break free
I want to break free

答案3

得分: 0

另一个选项(也许更符合"Pythonic",因为它使用了取模运算符)是使用Python中的itertools模块中提供的cycle()方法,代码如下:

lyrics = ["I want to break free", "I want to break free", "I want to break free", "yes, I want to break free"]
number_of_lines = 6

from itertools import cycle
line_in_lyrics_cycle = cycle(lyrics)

for _ in range(number_of_lines):
   print(next(line_in_lyrics_cycle))

由于line_in_lyrics_cycle是一个迭代器,您可以使用Python的next()方法从中获取一行,无需在循环中使用range()提供的索引值。这里的一个很好的副作用是,由于使用了next(),您可以像阅读解释一样阅读代码,理解它的功能。


为了完整起见,这里是Kelly Bundy在评论中提出的代码,对应于其他答案中chepner使用itertools的方法:

from itertools import islice, chain, repeat
q, r = divmod(number_of_lines, len(lyrics))
fulls = chain.from_iterable(repeat(lyrics, q))
tail = islice(lyrics, r)
for line in chain(fulls, tail):
    print(line)

这段代码在纯Python列表的术语中表达如下:

q, r = divmod(number_of_lines, len(lyrics))
lyrics_total = q * lyrics + lyrics[0:r]
for line in lyrics_total:
    print(line)

特别是看看第一个版本的代码,它充分利用了itertools迭代器的全部优点,使得

print(next(line_in_lyrics_cycle))

完全消失了,深埋在真的很难理解的代码下面,你可能需要三倍的文本行来解释这段代码的作用、如何以及为什么这么做。

在这种情况下,Pingu提供的代码需要更少的解释,因为您只需要理解取模运算符%的工作原理,而不必担心divmod和/或itertools。它之所以出色,是因为它的简洁性达到了循环的核心要点:

for i in range(number_of_lines):
    print(lyrics[i % len(lyrics)])
英文:

Another option (maybe a bit more "Pythonic" as using the modulo operator) is to use the cycle() method available in the with Python coming itertools module as follows:

lyrics = ["I want to break free", "I want to break free", "I want to break free", "yes, I want to break free"]
number_of_lines = 6

from itertools import cycle
line_in_lyrics_cycle = cycle(lyrics)

for _ in range(number_of_lines):
   print( next(line_in_lyrics_cycle) )

And because line_in_lyrics_cycle is an iterator you get a line out of it using the Python next() method and don't need the index value provided in the loop by range(). A nice side-effect here is that because of use of next() you can read the code like you would read the explanation what it does.


For the sake of completeness here the code proposed by Kelly Bundy in comments to the other itertools using answer by chepner:

from itertools import islice, chain, repeat
q, r = divmod(number_of_lines, len(lyrics))
fulls = chain.from_iterable(repeat(lyrics, q))
tail = islice(lyrics, r)
for line in chain(fulls, tail):
    print(line)

which does expressed in terms of Python list only:

q, r = divmod(number_of_lines, len(lyrics))
lyrics_total = q*lyrics+lyrics[0:r]
for line in lyrics_total:
    print(line)

Looking especially at the first version of the code making full use of the itertools iterators the entire BEAUTY of

   print( next(line_in_lyrics_cycle) )

is gone, buried so deep under the really hard to understand code, that you need probably three times the lines of text to explain what, how and why just this code.

In this context the code provided by Pingu needs much less explanations, because you only have to understand how the modulo % operator works and must not worry about divmod and/or itertools.

It excels because of its shortness got down to the bare point of cycling which the modulo operator is all about:

for i in range(number_of_lines):
    print(lyrics[i%len(lyrics)])

huangapple
  • 本文由 发表于 2023年2月6日 03:28:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75354941.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定