我需要在给定半径的给定索引周围的列表中搜索项目。目前,我使用此功能为搜索生成交替的偏移量:
def generateSearchIndizes(radius):
for i in range(1, radius + 1):
yield i
yield -i
执行搜索的代码如下所示:
for i in generateSearchIndizes():
if pred(myList[baseIndex + i]):
result = myList[baseIndex + i]
break # terminate search when first item is found
我的问题是,是否有更优雅的方式来生成搜索indizes,可能没有定义特殊功能?
答案 0 :(得分:4)
是否有更优雅的方式来生成搜索索引
我认为没有更优雅的方式。您的代码非常简单明了。
可能没有定义特殊功能吗?
是的,这绝对是可能的。
>>> [b for a in ((x,-x) for x in range(1, 10 + 1)) for b in a]
[1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10]
答案 1 :(得分:2)
这是我的理由:
from itertools import chain
>>> list(chain(*zip(range(1, 7), range(-7, 0)[::-1])))
[1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6]
根据需要进行调整。 :)
答案 2 :(得分:0)
也许是一个生成器表达式?
for i in (x/2 * (x%2 * 2 - 1) for x in xrange(2, radius*2)):
print i
它很短,适合你的“没有定义特殊功能”的要求......
但是,坦率地说,我仍然更喜欢使用那个特殊功能 - 只是为了拥有更清晰的代码。 :)
答案 3 :(得分:0)
为什么不用内循环来做这件事,而不是创建一个时髦的生成器:
found = False
for i_abs in range(1, radius+1):
for i in (i_abs, -i_abs):
listitem = myList[baseIndex + i]
if pred(listitem):
result = listitem
found = True
break # terminate search when first item is found
if found:
break
else:
# handling in case no match found for pred
其他一些评论:
你永远不会测试第0个元素
因为你是从左边开始测试的 而且,你应该停下来 i_abs达到了中途标记
我不喜欢重复列表索引操作,
宁可重复变量引用;所以我
解除了重复的myList[baseIndex+i]
和
已将其分配给listitem
你应该添加一些处理以防万一 找不到匹配的元素
而不是从内循环中断(
这里需要额外的found
变量
你可能会突破外围的for循环)
最好只是从...返回result
内环,
如:
for i_abs in range(1, radius+1):
for i in (i_abs, -i_abs):
listitem = myList[baseIndex + i]
if pred(listitem):
return listitem
然后没有需要中断管理或found
变量。
答案 4 :(得分:0)
为什么交替-i,我?只是做:
for i in range(-radius, radius+1):
listitem = myList[baseIndex + i]
if pred(listitem):
return listitem
或者,如果你必须从正面和背面接近以获得最外层的预先匹配,那么:
for i in sorted(range(-radius, radius+1), key=abs):
listitem = myList[baseIndex + i]
if pred(listitem):
return listitem
如果您经常这样做,只需构建sorted(range(-radius,radius+1),key=abs)
一次并保留它以备将来迭代。
如果你绝对不能使用第0个元素,只需在循环开始时插入if not i: continue
。
答案 5 :(得分:0)
这在我看来至少与单独的功能一样可读 - 并且可以说更容易理解:
radius = 3
for outerbounds in ((-r,r) for r in range(1,radius+1)):
for i in outerbounds :
print i
# -1
# 1
# -2
# 2
# -3
# 3
答案 6 :(得分:0)
您自己的解决方案,在生成器的开头添加yield 0
,是最直接的(也称为pythonic)。
这是一个使用不同算法的无限偏移生成器:
def gen_offsets():
offset= 0
yield offset
step= 1; sign= 1
while 1:
offset+= sign*step
yield offset
step+= 1; sign= -sign
编写上述算法的更奇怪(又名不那么pythonic :)的方法是:
import itertools as it, operator as op
def gen_offsets():
steps= it.imap(op.mul, it.count(1), it.cycle( (1, -1) ))
offset= 0
yield offset
for step in steps:
offset+= step
yield offset