简体   繁体   English

Python:如何在数组中以“ n”为单位选择性地切换布尔元素?

[英]Python: how do I selectively toggle boolean elements in steps of “n” in an array?

I have a string of 50 Christmas lights in a single line, and when they are first plugged in, all of the lights are off. 我在一行中有一串50个圣诞灯,当它们第一次插入时,所有的灯都熄灭了。 The lights are controlled by a single button, where every time the button is pressed, some of the lights flip their state (ie if they are off, they change to on; if they are on, they change to off). 灯由单个按钮控制,每次按下该按钮时,有些灯会翻转其状态(即,如果它们熄灭,它们将变为打开;如果它们点亮,则它们将变为关闭)。 The selection of lights which change depends on how many times the button has been pressed so far: 改变灯光的选择取决于到目前为止按钮被按下了多少次:

  • On the 1st press, the 1st, 2nd, 3rd, 4th, …, 50th lights change state 第一次按下时,第一,第二,第三,第四,…,第五十个灯会改变状态
  • On the 2nd press, the 2nd, 4th, 6th, …, lights change state; 在第二次按下时,第二,第四,第六,……灯会改变状态;
  • On the 3rd press, the 3rd, 6th, 9th, …, lights change state; 在第三次按时,第三,第六,第九,……灯会改变状态;
  • etc. 等等
  • On the nth press, the lights corresponding to all multiples of n change state. 在第n次按下时,对应于n的所有倍数的灯会更改状态。

How do I find out what lights are on after any given number of "n" presses? 在按给定次数的“ n”次按键后,如何找出什么灯亮?

I tried defining a boolean array to represent the lights. 我尝试定义一个布尔数组来表示灯光。 I wrote the following function: 我写了以下函数:

lightsarray = [False] * 50 ### All lights are off at start ###

def pressbutton(n):
    count = 0

    for count in range(0, n):   
        lightsarray[::int(n)] = [not y for y in lightsarray[::int(n)]]
        count = count + 1
        return lightsarray

Currently, the output for n = 1 is True, True, True, True, True, True... 当前,n = 1的输出为True, True, True, True, True, True...

The output for n = 2 is True, False, True, False, True, False... n = 2的输出为True, False, True, False, True, False...

So far so good. 到现在为止还挺好。 But for n = 3, I'm expecting True, False, False, False, True, True, True... 但是对于n = 3,我期望的是True, False, False, False, True, True, True...

But I'm getting True, False, False, True, False, False... 但是我得到了True, False, False, True, False, False...

I think I'm going wrong in assigning/getting the state of the array. 我想我在分配/获取数组状态时出错。 How do I correct this? 我该如何纠正? Or is there a better approach? 还是有更好的方法?

--EDIT-- Thanks for the responses everyone. -编辑-感谢大家的答复。 I implemented the changes and I'm getting the output you've suggested, but I'm not sure whether this matches the expected state of the lights. 我实现了更改,并获得了您建议的输出,但是不确定是否与灯光的预期状态匹配。 Keeping in mind that False = OFF and True = ON, let's look at the first 5 lights. 请记住,False = OFF,True = ON,让我们看一下前5个灯。 This is what is expected: 这是预期的:

For 0 presses, everything is off: 对于0按下,一切都关闭了:

False, False, False, False, False...

For 1 press, lights at every multiple of 1 are flipped: 按下1次,将以1的倍数翻转灯光:

True, True, True, True, True...

For 2 presses, the lights at every multiple of 2 are flipped: 对于2次按下,每2的倍数处的灯光会翻转一次:

True, False, True, False, True...

Note that the second and the fourth light were toggled, otherwise the rest remained unchanged. 请注意,第二个和第四个指示灯已切换,否则其余指示灯保持不变。

For 3 presses, the lights at every multiple of 3 are flipped: 对于3次按下,每3的倍数处的灯会翻转:

True, False, False, False, True...

However after making the changes, for instance, 2 presses gives False, True... not True, False... and 3 presses gives True, True, False, False, False... (there are two Trues in the beginning.) 但是,例如,在进行更改后,按2次将为False, True...而不是True, False...而按3次将给出True, True, False, False, False... (开头有两个True, True, False, False, False... 。 )

How do I correct this? 我该如何纠正? I hope that made sense. 我希望这是有道理的。

Your main problem is that you are using count in multiple ways in the same function. 您的主要问题是在同一个函数中以多种方式使用计数。 In essence, for count in range uses the same variable as count=0 , and count = count + 1 is modifying the loop variable. 本质上, for count in range使用与count=0相同的变量,而count = count + 1正在修改循环变量。

The other problem is that you are modifying the global lightsarray every time you run the function, so your output will depend on how you previously rand the function. 另一个问题是您每次运行该函数时都在修改全局lightsarray ,因此输出将取决于您之前对函数进行rand的方式。

Finally, if your pressbutton function is supposed to be showing the result of pressing the button n times, as it appears to be doing, you should be changing different lights every loop iteration, instead of flipping every n th light every loop iteration. 最后,如果您的pressbutton函数应该显示n次按下按钮的结果(看起来确实如此),则您应该在每次循环迭代中更改不同的灯光,而不是在每次循环迭代中翻转每第n个灯光。

You should just be doing 你应该在做

def pressbutton(n):
    lightsarray = [False] * 50 ### All lights are off at start ###
    for count in range(0, n):
        lightsarray[::count] = [not y for y in lightsarray[::count]]
    return lightsarray

If I understand the progression I would say that for each step k, we select first the kth element and then move to the 2kth element, 3k, 4k... 如果我了解进度,我会说,对于每个步骤k,我们首先选择第k个元素,然后移至第2k个元素,即3k,4k ...

This can be achieved using xrange (I prefer xrange to range since it doesn't fillup memory) wich take a step argument. 这可以通过使用xrange(我更喜欢xrange而不是range)来实现,该参数需要一个step参数。

here's an example of such progressions 这是这种进展的一个例子

for k in xrange(1, n + 1):
    print range(k, n, k)

That should do it, here's the output, looks similar to your example: 应该会做,这是输出,看起来类似于您的示例:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 4, 6, 8]
[3, 6, 9]
[4, 8]
[5]
[6]
[7]
[8]
[9]
[]

Notince that you don't have to go to n + 1, you can stop at n :) 注意,您不必转到n + 1,可以在n处停止:)

You switch the wrong lights; 您切换了错误的灯光; you are using n , not count , the loop counter, so you are always switching the wrong lights. 您使用n而不是count循环计数器,因此您总是在切换错误的灯。

You need to start counting at 1, and count up to n (so range to `n + 1). 您需要从1开始计数,最多计数到n (因此范围为`n + 1)。

Your indentation is wrong; 您的缩进是错误的; you return too early . 你回来太早了 Unindent the return statement to not be part of the loop. 取消缩进return语句使其不属于循环的一部分。

I'd also make the lightsarray value part of the function itself, don't use a global here, as it'll be mutated each time you call the function, making it harder to test the function itself. 我还要使lightsarray值成为函数本身的一部分,不要在此处使用全局变量,因为每次调用函数时都会对其进行突变,这使得测试函数本身更加困难。

Last but not least, there is no need to increment count manually, that's what the for loop is already doing for you: 最后但并非最不重要的一点是,不需要手动递增count ,这就是for循环已为您完成的工作:

def pressbutton(n):
    lightsarray = [False] * 50 ### All lights are off at start ###
    for count in range(1, n + 1):   
        lightsarray[::count] = [not y for y in lightsarray[::count]]
    return lightsarray

Now this works as expected: 现在,这可以按预期工作:

>>> pressbutton(1)
[True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
>>> pressbutton(2)
[False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True, False, True]
>>> pressbutton(3)
[True, True, False, False, False, True, True, True, False, False, False, True, True, True, False, False, False, True, True, True, False, False, False, True, True, True, False, False, False, True, True, True, False, False, False, True, True, True, False, False, False, True, True, True, False, False, False, True, True, True]

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

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