简体   繁体   English

来回循环 Python

[英]Back and forth loop Python

I want to create an infinite loop that counts up and down from 0 to 100 to 0 (and so on) and only stops when some convergence criterion inside the loop is met, so basically something like this:我想创建一个无限循环,从 0 到 100 到 0(等等)上下计数,并且只有在满足循环内的某些收敛标准时才停止,所以基本上是这样的:

for i in range(0, infinity):
    for j in range(0, 100, 1):
        print(j) # (in my case 100 lines of code)
    for j in range(100, 0, -1):
        print(j) # (same 100 lines of code as above)

Is there any way to merge the two for loops over j into one so that I don't have write out the same code inside the loops twice?有没有办法将 j 上的两个 for 循环合并为一个,这样我就不会在循环内写出相同的代码两次?

Use the chain method of itertools使用itertoolschain方法

import itertools
for i in range(0, infinity):
    for j in itertools.chain(range(0, 100, 1), range(100, 0, -1)):
        print(j) # (in my case 100 lines of code)

As suggested by @Chepner, you can use itertools.cycle() for the infinite loop:正如@Chepner 所建议的,您可以将itertools.cycle()用于无限循环:

from itertools import cycle, chain

for i in cycle(chain(range(0, 100, 1), range(100, 0, -1))):
    ....

As well as the other answers you can use a bit of maths:除了其他答案之外,您还可以使用一些数学知识:

while(True):
    for i in range(200):
        if i > 100:
            i = 200 - i

Here's yet another possibility:这是另一种可能性:

while notConverged:
    for i in xrange(-100, 101):
        print 100 - abs(i)

If you've got a repeated set of code, use a function to save space and effort:如果您有一组重复的代码,请使用函数来节省空间和精力:

def function(x, y, x, num_from_for_loop):
    # 100 lines of code 

while not condition:
    for i in range(1, 101):
        if condition:
            break
        function(x, y, z, i)
    for i in range(100, 0, -1):
        if condition:
            break
        function(x, y, z, i)

You could even use a while True你甚至可以使用一段while True

If you're using Python 3.5+, you can using generic unpacking:如果您使用的是 Python 3.5+,则可以使用通用解包:

for j in (*range(0, 100, 1), *range(100, 0, -1)):

or prior to Python 3.5, you can use itertools.chain :或在 Python 3.5 之前,您可以使用itertools.chain

from itertools import chain

...

for j in chain(range(0, 100, 1), range(100, 0, -1)):
up = True # since we want to go from 0 to 100 first

while True: #for infinite loop

    # For up == True we will print 0-->100 (0,100,1)
    # For up == False we will print 100-->0 (100,0,-1)


    start,stop,step = (0,100,1) if up else (100,0,-1)
    for i in range(start,stop,step):
        print(i)

    up = not up # if we have just printed from 0-->100 (ie up==True), we want to print 100-->0 next so make up False ie up = not up( True) 

    # up will help toggle, between 0-->100 and 100-->0
def up_down(lowest_value, highest_value):
    current = lowest_value
    delta = 1
    while True: # Begin infinite loop
        yield current
        current += delta
        if current <= lowest_value or current >= highest_value:
            delta *= -1 # Turn around when either limit is hit

This defines a generator, which will continue to yield values for as long as you need.这定义了一个生成器,只要您需要,它将继续产生值。 For example:例如:

>>> u = up_down(0, 10)
>>> count = 0
>>> for j in u:
    print(j) # for demonstration purposes
    count += 1 # your other 100 lines of code here
    if count >= 25: # your ending condition here
        break


0
1
2
3
4
5
6
7
8
9
10
9
8
7
6
5
4
3
2
1
0
1
2
3
4

This is more of a partial answer than a direct answer to your question, but you can also use the notion of trigonometric functions and their oscillation to imitate a 'back and forth' loop.这比直接回答您的问题更多的是部分答案,但您也可以使用三角函数及其振荡的概念来模仿“来回”循环。

If we have a cos function with an amplitude of 100, shifted left and upwards so that f(x) = 0 and 0 <= f(x) <= 100 , we then have the formula f(x) = 50(cos(x-pi)+1) (plot of graph may be foundhere . The range is what you require, and oscillation occurs so there's no need to negate any values.如果我们有一个幅度为 100 的 cos 函数,向左和向上移动,使得f(x) = 00 <= f(x) <= 100 ,我们就有公式f(x) = 50(cos(x-pi)+1) (可以在此处找到图表。范围是您需要的,并且会发生振荡,因此无需否定任何值。

>>> from math import cos, pi
>>> f = lambda x: 50*(cos(x-pi)+1)
>>> f(0)
0.0
>>> f(pi/2)
50.0
>>> f(pi)
100.0
>>> f(3*pi/2)
50.0
>>> f(2*pi)
0.0

The issue of course comes in that the function doesn't give integer values so easily, thus it's not that helpful - but this may be useful for future readers where trigonometric functions might be helpful for their case.当然,问题在于该函数不能轻易给出整数值,因此它没有那么有用 - 但这可能对未来的读者有用,因为三角函数可能对他们的情况有所帮助。

I had a similar problem a while ago where I also wanted to create values in the form of an infinite triangle wave, but wanted to step over some values.前段时间我有一个类似的问题,我也想以无限三角波的形式创建值,但想跨过一些值。 I ended up using a generator (and the range function as other also have been using):我最终使用了一个生成器(以及其他也一直在使用的范围函数):

def tri_wave(min, max, step=1):
    while True:
        yield from range(min, max, step)
        yield from range(max, min, -1 * step)

With carefully selected values on min, max and step (ie evenly divisible),在最小值、最大值和步长上仔细选择值(即可整除),

for value in tri_wave(0, 8, 2):
    print(value, end=", ")

I get the min and max value only once, which was my goal:我只得到一次最小值和最大值,这是我的目标:

...0, 2, 4, 6, 8, 6, 4, 2, 0, 2, 4, 6, 8, 6, 4...

I was using Python 3.6 at the time.我当时使用的是 Python 3.6。

I became curious if it's possible to implement such kind of triangle oscillator without conditions and enumerations.我开始好奇是否有可能在没有条件和枚举的情况下实现这种三角形振荡器。 Well, one option is the following:好吧,一种选择如下:

def oscillator(magnitude):
   i = 0
   x = y = -1
   double_magnitude = magnitude + magnitude

   while True:
       yield i
       x = (x + 1) * (1 - (x // (double_magnitude - 1)))  # instead of (x + 1) % double_magnitude
       y = (y + 1) * (1 - (y // (magnitude - 1)))         # instead of (y + 1) % magnitude
       difference = x - y                                 # difference ∈ {0, magnitude}
       derivative = (-1 * (difference > 0) + 1 * (difference == 0))
       i += derivative

The idea behind this is to take 2 sawtooth waves with different periods and subtract one from another.这背后的想法是采用 2 个不同周期的锯齿波并从另一个中减去一个。 The result will be a square wave with values in {0, magnitude}.结果将是一个值为 {0, 幅度} 的方波。 Then we just substitute {0, magnitude} with {-1, +1} respectively to get derivative values for our target signal.然后我们只需用 {-1, +1} 分别替换 {0,magnitude} 以获得目标信号的导数值。

Let's look at example with magnitude = 5 :让我们看一下magnitude = 5的示例:

o = oscillator(5)
[next(o) for _ in range(21)]

This outputs [0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0] .这输出[0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0]

If abs() is allowed, it can be used for simplicity.如果abs()被允许,它可以用于简单起见。 For example, the following code gives the same output as above:例如,以下代码给出与上面相同的输出:

[abs(5 - ((x + 5) % 10)) for x in range(21)]

Here is a simple and straightforward solution that does not require any imports:这是一个简单直接的解决方案,不需要任何导入:

index = 0
constant = 100

while True:
    print(index)
    if index == constant:
        step = -1
    elif index == 0:
        step = 1

    index += step

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM