【问题标题】:Iterate though list on each for loop iteration遍历每个 for 循环迭代的列表
【发布时间】:2023-03-25 20:23:01
【问题描述】:

我正在编写以下代码:

mylist = [1,2,3,4,5,6,7,8,9,10.....]
for x in range(0, len(mylist), 3):
    value = mylist[x:x + 3]
    print(value)

基本上,我一次在mylist 中取 3 个项目,代码比这更大,但我做了很多事情,让它们从中返回一个值,然后它取接下来的 3 个项目来自mylist 并一直这样做到此列表的末尾。

但现在我有一个问题,我需要识别每个迭代,但它们遵循一个规则:

第一个循环来自 A,第二个来自 B,第三个来自 C。 当它到达第三个时,它从 A 重新开始,所以我想做的是这样的:

mylist[0:3]来自A

mylist[3:6] 来自 B

mylist[6:9] 来自 C

mylist[9:12]来自A

mylist[12:15]来自B......

最初的想法是实现一个从 A 到 C 的标识符,每次迭代它都会跳转到下一个标识符,但是当它到达 C 时,它会返回到 A。

所以输出看起来像这样:

[1,2,3] from A
[4,5,6] from B
[6,7,8] from C
[9,10,11] from A
[12,13,14] from B
[15,16,17] from C
[18,19,20] from A.....

我的错误解决方案: 创建 identifiers = [A,B,C] 乘以 mylist 的 len -> identifiers = [A,B,C]*len(mylist) 因此,A、B 和 C 的数量与它需要识别的 mylist 数字相同。然后在我的 for 循环中,我添加一个计数器,为自身添加 +1 并访问我的列表的索引。

mylist = [1,2,3,4,5,6,7,8,9,10.....]
identifier = ['A','B','C']*len(mylist)
counter = -1
for x in range(0, len(mylist), 3):

    value = mylist[x:x + 3]
    counter += 1
    print(value, identifier[counter])

但它太丑了,一点也不快。有谁知道更快的方法吗?

【问题讨论】:

  • 什么是 A、B 和 C? 3个清单?我真的不明白你的代码应该做什么。
  • 它只是一个字符串,我需要返回有界的值

标签: python python-3.x list for-loop


【解决方案1】:

循环、压缩和解压:

mylist = [1,2,3,4,5,6,7,8,9,10]

for value, iden in zip(mylist, itertools.cycle('A', 'B', 'C')):
    print(value, iden)

输出:

1 A
2 B
3 C
4 A
5 B
6 C
7 A
8 B
9 C
10 A

【讨论】:

  • 也许它需要对我的列表进行一些重塑才能获得 n 行和 3 列(以完全符合预期结果)?你怎么看?
【解决方案2】:

您始终可以使用生成器来迭代您的标识符:

def infinite_generator(seq):
    while True:
        for item in seq:
            yield item

初始化标识符:

identifier = infinite_generator(['A', 'B', 'C'])

然后在你的循环中:

print(value, next(identifier))

【讨论】:

【解决方案3】:

基于适合您问题的Ignacio's answer
你可以先把reshape你的list变成一个包含3个元素的list of arrays

import pandas as pd
import numpy as np
import itertools

mylist = [1,2,3,4,5,6,7,8,9,10]
_reshaped = np.reshape(mylist[:len(mylist)-len(mylist)%3],(-1,3))

print(_reshaped)
[[1 2 3]
 [4 5 6]
 [7 8 9]]

请注意,它可以工作,因为您的列表包含 3 个元素的多个元素(因此您需要删除最后一个元素以遵守此条件,mylist[:len(mylist)-len(mylist)%3])-Understanding slice notation
请参阅 UPDATE 部分了解适合您问题的重塑。

然后将 Ignacio 的解决方案应用到重构列表中

for value, iden in zip(_reshaped, itertools.cycle(('A', 'B', 'C'))):
    print(value, iden)

[1 2 3] A
[4 5 6] B
[7 8 9] C

更新
您可以使用@NedBatchelder's chunk generator 按预期重塑您的数组:

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

mylist = [1,2,3,4,5,6,7,8,9,10]

_reshaped = list(chunks(mylist, 3))
print(_reshaped)
    [[1 2 3]
     [4 5 6]
     [7 8 9]
     [10]]

然后:

for value, iden in zip(_reshaped, itertools.cycle(('A', 'B', 'C'))):
    print(value, iden)

[1 2 3] A
[4 5 6] B
[7 8 9] C
[10] A

表演

您的解决方案:每个循环 1.32 ms ± 94.3 µs
使用重构列表:每个循环 1.32 ms ± 84.6 µs

您注意到等效结果在性能方面没有敏感差异。

【讨论】:

  • 感谢您的计时结果,我没想到会有很大的差异,但由于我的主要目标是性能,因为无论如何最终目标已经达到,欢迎每项改进
  • 我正在使用来自 itertools 的生成器和 next(generator) 函数,事实证明它比我正在做的更快,我将尝试你的解决方案,看看什么更快
【解决方案4】:

您可以为切片创建一个生成器:

grouped_items = zip(*[seq[i::3] for i in range(3)])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多