[英]counting up and then down a range in python
I am trying to program a standard snake draft, where team A pick, team B, team C, team C, team B, team A, ad nauseum. 我正在尝试编制一个标准的蛇选项,其中A队选秀,B队,C队,C队,B队,A队,恶心。
If pick number 13 (or pick number x) just happened how can I figure which team picks next for n number of teams. 如果选秀号码13(或选秀号码x)刚刚发生,我怎样才能确定哪支球队接下来会选择n队。
I have something like: 我有类似的东西:
def slot(n,x):
direction = 'down' if (int(x/n) & 1) else 'up'
spot = (x % n) + 1
slot = spot if direction == 'up' else ((n+1) - spot)
return slot
I have feeling there is a simpler, more pythonic what than this solution. 我觉得有一个比这个解决方案更简单,更pythonic的东西。 Anyone care to take a hack at it?
任何人都想关注它吗?
So I played around a little more. 所以我玩了一点。 I am looking for the return of a single value, rather than the best way to count over a looped list.
我正在寻找单个值的返回,而不是计算循环列表的最佳方法。 The most literal answer might be:
最直接的答案可能是:
def slot(n, x): # 0.15757 sec for 100,000x
number_range = range(1, n+1) + range(n,0, -1)
index = x % (n*2)
return number_range[index]
This creates a list [1,2,3,4,4,3,2,1], figures out the index (eg 13 % (4*2) = 5), and then returns the index value from the list (eg 4). 这会创建一个列表[1,2,3,4,4,3,2,1],计算出索引(例如13%(4 * 2)= 5),然后从列表中返回索引值(例如4)。 The longer the list, the slower the function.
列表越长,功能越慢。
We can use some logic to cut the list making in half. 我们可以使用一些逻辑将列表减半。 If we are counting up (ie
(int(x/n) & 1)
returns False), we get the obvious index value (x % n), else we subtract that value from n+1: 如果我们正在计数(即
(int(x/n) & 1)
返回False),我们得到明显的索引值(x%n),否则我们从n + 1中减去该值:
def slot(n, x): # 0.11982 sec for 100,000x
number_range = range(1, n+1) + range(n,0, -1)
index = ((n-1) - (x % n)) if (int(x/n) & 1) else (x % n)
return number_range[index]
Still avoiding a list altogether is fastest: 完全避免列表是最快的:
def slot(n, x): # 0.07275 sec for 100,000x
spot = (x % n) + 1
slot = ((n+1) - spot) if (int(x/n) & 1) else spot
return slot
And if I hold the list as variable rather than spawning one: 如果我将列表保存为变量而不是产生一个:
number_list = [1,2,3,4,5,6,7,8,9,10,11,12,12,11,10,9,8,7,6,5,4,3,2,1]
def slot(n, x): # 0.03638 sec for 100,000x
return number_list[x % (n*2)]
Why not use itertools cycle
function: 为什么不使用itertools
cycle
函数:
from itertools import cycle
li = range(1, n+1) + range(n, 0, -1) # e.g. [1, 2, 3, 4, 4, 3, 2, 1]
it = cycle(li)
[next(it) for _ in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]
Note: previously I had answered how to run up and down, as follows: 注意:之前我已经回答了如何上下运行,如下:
it = cycle(range(1, n+1) + range(n, 0, -1)) #e.g. [1, 2, 3, 4, 3, 2, 1, 2, 3, ...]
Here's a generator that will fulfill what you want. 这是一台能满足您的需求的发电机。
def draft(n):
while True:
for i in xrange(1,n+1):
yield i
for i in xrange(n,0,-1):
yield i
>>> d = draft(3)
>>> [d.next() for _ in xrange(12)]
[1, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 1]
from itertools import chain, cycle
def cycle_up_and_down(first, last):
up = xrange(first, last+1, 1)
down = xrange(last, first-1, -1)
return cycle(chain(up, down))
turns = cycle_up_and_down(1, 4)
print [next(turns) for n in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]
Here is a list of numbers that counts up, then down: 这是一个数字列表,然后向下计数:
>>> [ -abs(5-i)+5 for i in range(0,10) ]
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]
Written out: 写出来:
count_up_to = 5
for i in range( 0, count_up_to*2 ):
the_number_you_care_about = -abs(count_up_to-i) + count_up_to
# do stuff with the_number_you_care_about
Easier to read: 更易于阅读:
>>> list( range(0,5) ) + list( range( 5, 0, -1 ) )
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]
Written out: 写出来:
count_up_to = 5
for i in list( range(0,5) ) + list( range(5, 0, -1) ):
# i is the number you care about
Another way: 其他方式:
from itertools import chain
for i in chain( range(0,5), range(5,0,-1) ):
# i is the number you care about
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.