Python - 从列表的中间开始迭代,然后检查任一侧
Python - iterating beginning with the middle of the list and then checking either side
真的不确定这适合哪里。说,我有一个列表:
>>>a = [1, 2, 3, 4, 5, 6, 7]
我怎样才能以这样的方式迭代它,它会首先检查 4,然后是 5,然后是 3,然后是 6,然后是 2(对于更大的列表以此类推)?我只能计算出中间部分
>>>middle = [len(a)/2 if len(a) % 2 = 0 else ((len(a)+1)/2)]
我真的不确定如何应用它,我也不确定我的中间方法是最好的方法。我想过获取两个索引,并在每次迭代后,从每个相应的索引中加 1 和减 1,但不知道如何使 for 循环遵守这些规则。
关于我为什么需要这个;它用于分析纸牌游戏中的有效玩法,将从给定手牌的中间牌到每一端进行检查,直到可以打出有效牌为止。
首先,here 是一个非常有用的通用实用程序,用于交错两个序列:
def imerge(a, b):
for i, j in itertools.izip_longest(a,b):
yield i
if j is not None:
yield j
这样,您只需要 imerge
a[len(a) / 2: ]
和
reversed(a[: len(a) / 2])
您可以继续从列表中间删除:
lst = range(1, 8)
while lst:
print lst.pop(len(lst)/2)
这不是性能方面的最佳解决方案(从列表中删除项目很昂贵),但它很简单 - 对于一个简单的游戏来说已经足够好了。
编辑:
性能更稳定的解决方案是生成器,它计算元素位置:
def iter_from_middle(lst):
try:
middle = len(lst)/2
yield lst[middle]
for shift in range(1, middle+1):
# order is important!
yield lst[middle - shift]
yield lst[middle + shift]
except IndexError: # occures on lst[len(lst)] or for empty list
raise StopIteration
你也可以玩指数游戏,例如:
>>> a = [1, 2, 3, 4, 5, 6, 7]
>>> [a[(len(a) + (~i, i)[i%2]) // 2] for i in range(len(a))]
[4, 5, 3, 6, 2, 7, 1]
>>> a = [1, 2, 3, 4, 5, 6, 7, 8]
>>> [a[(len(a) + (~i, i)[i%2]) // 2] for i in range(len(a))]
[4, 5, 3, 6, 2, 7, 1, 8]
这是一个生成器,可以为任何给定的长度生成交替索引。它可能是 improved/shorter,但它有效。
def backNforth(length):
if length == 0:
return
else:
middle = length//2
yield middle
for ind in range(1, middle + 1):
if length > (2 * ind - 1):
yield middle - ind
if length > (2 * ind):
yield middle + ind
# for testing:
if __name__ == '__main__':
r = range(9)
for _ in backNforth(len(r)):
print(r[_])
使用它,您可以按照您想要的顺序生成项目列表:
a = [1, 2, 3, 4, 5, 6, 7]
a_prime = [a[_] for _ in backNforth(len(a))]
除了中间的元素,我还需要它们的索引。我发现 Wasowski 的回答很有帮助,并对其进行了修改:
def iter_from_middle(lst):
index = len(lst)//2
for i in range(len(lst)):
index = index+i*(-1)**i
yield index, lst[index]
>>> my_list = [10, 11, 12, 13, 14, 15]
>>> [(index, item) for index, item in iter_from_middle(my_list)]
[(3, 13), (2, 12), (4, 14), (1, 11), (5, 15), (0, 10)]
真的不确定这适合哪里。说,我有一个列表:
>>>a = [1, 2, 3, 4, 5, 6, 7]
我怎样才能以这样的方式迭代它,它会首先检查 4,然后是 5,然后是 3,然后是 6,然后是 2(对于更大的列表以此类推)?我只能计算出中间部分
>>>middle = [len(a)/2 if len(a) % 2 = 0 else ((len(a)+1)/2)]
我真的不确定如何应用它,我也不确定我的中间方法是最好的方法。我想过获取两个索引,并在每次迭代后,从每个相应的索引中加 1 和减 1,但不知道如何使 for 循环遵守这些规则。
关于我为什么需要这个;它用于分析纸牌游戏中的有效玩法,将从给定手牌的中间牌到每一端进行检查,直到可以打出有效牌为止。
首先,here 是一个非常有用的通用实用程序,用于交错两个序列:
def imerge(a, b):
for i, j in itertools.izip_longest(a,b):
yield i
if j is not None:
yield j
这样,您只需要 imerge
a[len(a) / 2: ]
和
reversed(a[: len(a) / 2])
您可以继续从列表中间删除:
lst = range(1, 8)
while lst:
print lst.pop(len(lst)/2)
这不是性能方面的最佳解决方案(从列表中删除项目很昂贵),但它很简单 - 对于一个简单的游戏来说已经足够好了。
编辑:
性能更稳定的解决方案是生成器,它计算元素位置:
def iter_from_middle(lst):
try:
middle = len(lst)/2
yield lst[middle]
for shift in range(1, middle+1):
# order is important!
yield lst[middle - shift]
yield lst[middle + shift]
except IndexError: # occures on lst[len(lst)] or for empty list
raise StopIteration
你也可以玩指数游戏,例如:
>>> a = [1, 2, 3, 4, 5, 6, 7]
>>> [a[(len(a) + (~i, i)[i%2]) // 2] for i in range(len(a))]
[4, 5, 3, 6, 2, 7, 1]
>>> a = [1, 2, 3, 4, 5, 6, 7, 8]
>>> [a[(len(a) + (~i, i)[i%2]) // 2] for i in range(len(a))]
[4, 5, 3, 6, 2, 7, 1, 8]
这是一个生成器,可以为任何给定的长度生成交替索引。它可能是 improved/shorter,但它有效。
def backNforth(length):
if length == 0:
return
else:
middle = length//2
yield middle
for ind in range(1, middle + 1):
if length > (2 * ind - 1):
yield middle - ind
if length > (2 * ind):
yield middle + ind
# for testing:
if __name__ == '__main__':
r = range(9)
for _ in backNforth(len(r)):
print(r[_])
使用它,您可以按照您想要的顺序生成项目列表:
a = [1, 2, 3, 4, 5, 6, 7]
a_prime = [a[_] for _ in backNforth(len(a))]
除了中间的元素,我还需要它们的索引。我发现 Wasowski 的回答很有帮助,并对其进行了修改:
def iter_from_middle(lst):
index = len(lst)//2
for i in range(len(lst)):
index = index+i*(-1)**i
yield index, lst[index]
>>> my_list = [10, 11, 12, 13, 14, 15]
>>> [(index, item) for index, item in iter_from_middle(my_list)]
[(3, 13), (2, 12), (4, 14), (1, 11), (5, 15), (0, 10)]