1

我什至不知道从哪里开始为这个问题提供适当的标题。如果可以的话,请提出更好的建议。

我有一个要迭代的列表,但不是每次迭代处理 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()
4

3 回答 3

1

使用切片:

def rotate(seq, k):
    return seq[k:] + seq[:k]

l = ['abc', 'def', 'ghi', 'jkl']
for i, j, k in zip(rotate(l, -1), l, rotate(l, 1)):
    print(i, j, k)
于 2022-03-04T06:08:38.517 回答
0

尝试这个:

def iter_item(lst: list) -> list:
    for i in range(len(lst)):
        start = len(lst) - 1 if i < 1 else i - 1
        end = (start + 3) % len(lst)
        if end > start:
            print(*lst[start:end])
        else:
            print(*(lst[start:] + lst[:end]))


iter_item(['abc', 'def', 'ghi', 'jkl'])
于 2022-03-04T05:50:35.343 回答
0

您可以在滑动窗口函数之上构建它:

def cyclic_triples(seq):
    if not seq:
        return

    if len(seq) == 1:
        yield (seq[0], seq[0], seq[0])
        return

    yield (seq[-1], seq[0], seq[1])
    yield from map(tuple, windows(seq, 3))
    yield (seq[-2], seq[-1], seq[0])

其中一个示例实现windows是:

from collections import deque

def windows(iterable, size):
    d = deque((), size)
    it = iter(iterable)

    for i in range(size - 1):
        d.append(next(it, None))

    for x in it:
        d.append(x)
        yield d
于 2022-03-04T05:48:56.443 回答