简体   繁体   English

更新列表理解中的 if 条件内的变量

[英]updating a variable inside an if condition within a list comprehension

i tried my best to write the following code in a list comprehension but ended up getting wrong我尽力在列表理解中编写以下代码,但最终出错了

for i in range(1,n+1):
    L.append(i+(k*sin))
    if(i % (k) == 0):
        sin*=-1


return [i+(k*sin) if(i % (k*2) == 0) sin*=-1 for i in range(1,n+1)]

You can do this with a list comprehension, but you should take a different approach.您可以通过列表推导来做到这一点,但您应该采用不同的方法。

Let's say k == 3 : then your sequence will look like this:假设k == 3 :那么您的序列将如下所示:

1 + k*sin
2 + k*sin
3 + k*sin
4 + -k*sin
5 + -k*sin
6 + -k*sin
7 + k*sin
8 + k*sin
9 + k*sin
 ...

Basically, you just want a list comprehension that looks like基本上,您只需要一个看起来像的列表理解

[i + n*sin for i, n in zip(range(1, n+1), ???)]

The question is, what do we replace ???问题是,我们要替换什么??? with to get our sequence of repeating k and -k values?来获得我们重复的k-k值的序列?

The itertools module provides several tools for generating this: itertools模块提供了几个工具来生成它:

  • repeat - repeat a value some number of times repeat - 重复一个值若干次
  • chain - concatenate two or more sequences into a single sequence chain - 将两个或多个序列连接成一个序列
  • cycle - cycle through the values in a sequence repeatedly cycle - 重复循环遍历序列中的值

In this case, it's在这种情况下,它是

cycle(chain(repeat(k, k), repeat(-k, k)))

giving you给你

from itertools import repeat, chain, cycle


[i + n*sin for i, n in zip(range(1, n+1), cycle(chain(repeat(k, k), repeat(-k, k)))]

zip ensures we only take a finite number of values from the infinite sequence. zip确保我们只从无限序列中获取有限数量的值。

Another approach is to use another tool from itertool , islice , to take only the first n values from the cycle.另一种方法是使用来自itertool的另一个工具islice ,仅从循环中获取前n值。 Then we don't need range anymore;然后我们不再需要range we can use enumerate to number those values from 1 to n instead.我们可以使用enumerate将这些值从1编号为n

from itertools import repeat, chain, cycle, islice


[i + n*sin for i, n in enumerate(islice(cycle(chain(repeat(k, k), repeat(-k, k))), n), start=1]

Both read better if you define ks first:如果您先定义ks ,则两者都读得更好:

ks = cycle(chain(repeat(k, k), repeat(-k, k)))
[i + n*sin for i, n in zip(range(1, n+1), ks)]

or或者

ks = cycle(chain(repeat(k, k), repeat(-k, k)))
[i + n*sin for i, n in enumerate(islice(ks, n), start=1)]

You can also optimize this a bit by repeating the value of k*sin , rather than performing the multiplication for each element of the list.您还可以通过重复k*sin的值来优化这一点,而不是对列表的每个元素执行乘法。

ks = cycle(chain(repeat(k*sin, k), repeat(-k*sin, k)))
[i + n for i, n in ...] # using either zip or enumerate as before

What you want is to mathematically formulate your problem a little bit better, than it can easily be represented as a list comprehension.你想要的是在数学上更好地表达你的问题,而不是它可以很容易地表示为列表理解。

In essence, you want the a formula for the signal of sin which is dependent on the index i and on k that will invert the signal every k .本质上,您需要sin信号的公式,该公式取决于索引ik ,它将在每个k反转信号。 That is represented by (-1) ** (i - 1) // k .这由(-1) ** (i - 1) // k

So, if you include that into your code, you should arrive at exactly what you want:因此,如果您将其包含到您的代码中,您应该得到您想要的:

return [i + (k * ((-1) ** ((i - 1) // k)) * sin) for i in range(1,n+1)]

Hope that helps!希望有帮助!

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

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