我什至不知道从哪里开始为这个问题提供适当的标题。如果可以的话,请提出更好的建议。
我有一个要迭代的列表,但不是每次迭代处理 1 个值,而是要处理 3 个:
* 前一个值
* 当前值
* 下一个值
所以很明显我在这里使用了一些包装,即,对于第一次迭代,我使用列表中的最后一个值作为前一个值。同样,对于最后一次迭代,我使用列表中的第一个值作为下一个值。
例如,如果我的清单是:['abc', 'def', 'ghi', 'jkl']
迭代它的结果将是:
jkl abc def
abc def ghi
def ghi jkl
ghi jkl abc
我提出了 2 个版本的通用函数,它们根据上述要求返回一个元组列表。
第一个从原始列表创建多个切片,然后使用 zip 创建元组列表。可能不是最节省内存的解决方案......
第二个使用 itertools 链和 islice 函数来做同样的事情,但不创建数组的多个副本。但是,由于迭代器的性质,我必须不断创建移位列表的新副本。那,它看起来很混乱,而且不是很pythonic。
我的问题是,是否有更 Pythonic 的方式使用不同的itertools函数或更好的 itertools 配方来做我想做的事。
两个函数都采用相同的参数
*the_list
要操作的值
*n
返回值中每个元组中的项目数
*offset
给定的位置数(正数或负数)以将原始输入移动
对于我们希望元组包含先前值的用例,需要移动输入。
from itertools import islice, chain
def wrapit(the_list, n, offset=0):
shifted_list = the_list[offset:] + the_list[:offset]
list_of_lists = [shifted_list[i:] + shifted_list[:i] for i in range(n)]
return zip(*list_of_lists)
def iter_wrapit(the_list, n, offset=0):
offset = offset if offset >= 0 else len(the_list) + offset
lst_list = [
chain(
islice(chain(islice(the_list, offset, None), islice(the_list, 0, offset)), i, None),
islice(chain(islice(the_list, offset, None), islice(the_list, 0, offset)), 0, i)
) for i in range(n)
]
return zip(*lst_list)
def main():
a = "abc def ghi jkl".split()
print(a)
print("-" * 10)
for t in wrapit(a, 3, -1):
print(*t)
print("-" * 10)
for t in iter_wrapit(a, 3, -1):
print(*t)
print("-" * 10)
if __name__ == "__main__":
main()