【问题标题】:Processing alternate element in for loop without using index value在不使用索引值的情况下处理 for 循环中的替代元素
【发布时间】:2017-11-10 04:13:32
【问题描述】:

我有一个带有字典的元素列表,为简单起见,我将它们写成字符串:

ls = ['element1', 'element2', 'element3', 'element4', 'element5', 'element6', 'element7', 'element8', 'element9', 'element10']

我正在尝试按如下方式处理列表中的一对元素:

#m1. Step for loop by size two with if condition 
for x in ls:
    if ls.index(x)%2 == 0:
        # my code to be process
        print(x) # for simplicity I just printed element


#m2. tried another way like below:
for x in range(0, len(ls), 2):
    # this way give me output of alternate element from list
    print(ls[x])

有什么方法可以在迭代m1 中的列表项时只获取备用元素,就像m2 一样?

【问题讨论】:

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


    【解决方案1】:

    您可以使用itertools.islice,步长为2:

    import itertools
    
    for item in itertools.islice(ls, None, None, 2):  # start and stop None, step 2
        print(item)
    

    哪些打印:

    element1
    element3
    element5
    element7
    element9
    

    islice 不会创建新列表,因此它比l[::2] 更节省内存,但会以性能为代价(会慢一些)。

    时序对比:

    (注意:我使用 IPythons %%timeit 来测量执行时间。)

    对于短序列[::2] 更快:

    ls = list(range(100))
    
    %%timeit
    
    for item in itertools.islice(ls, None, None, 2):
        pass
    

    每个循环 3.81 µs ± 90 ns(7 次运行的平均值 ± 标准偏差,每次 100000 次循环)

    %%timeit
    
    for item in ls[::2]:
        pass
    

    每个循环 3.16 µs ± 82 ns(7 次运行的平均值 ± 标准偏差,每次 100000 次循环)

    但是对于长序列islice 会更快并且需要更少的内存:

    import itertools
    
    ls = list(range(100000))
    
    %%timeit
    
    for item in itertools.islice(ls, None, None, 2):
        pass
    

    每个循环 3.14 毫秒 ± 53.9 微秒(7 次运行的平均值 ± 标准偏差,每次 100 次循环)

    %%timeit
    
    for item in ls[::2]:
        pass
    

    每个循环 4.82 ms ± 132 µs(7 次运行的平均值 ± 标准偏差,每次 100 个循环)

    一个例外:如果您希望结果为list,那么切片[::2] 总是会更快,但如果您想对其进行迭代,那么islice 应该是首选选项。

    【讨论】:

    • 看起来有点矫枉过正
    • @AzatIbrakov 你能详细说明你所说的“矫枉过正”是什么意思吗? itertools 中的函数非常轻量级并且非常节省内存。
    • islice 在我们处理迭代器(如文件对象或无限生成器)时很棒,但对于lists(和其他序列),我认为使用切片会更好
    • @AzatIbrakov 这并不容易概括。对于短序列,itertools 可能没有意义,但对于长序列,它们可以提供巨大的好处(速度和内存)。该问题表明,许多显示的代码都已简化,因此在这种情况下考虑内存可能是值得的。
    • 忽略一次性导入在考虑时间消耗方面非常稳定,但并非总是如此。感谢您的帮助。
    【解决方案2】:

    您可以分两步对列表进行切片;利用内存:

    for x in ls[::2]:
        print(x)
    

    【讨论】:

    • 感谢您提供方法。但我已经通过将ls 乘以 100 来测试这个循环,它所消耗的时间范围从0.0007168804017688313 秒到0.0013200705195567028 秒。有什么方法可以稳定它以最小化时间消耗?
    • @Gahan 你用什么来计时?你应该使用timeit。两次运行不足以获得可靠的计时。
    猜你喜欢
    • 2020-02-26
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 2021-06-24
    • 2022-01-22
    相关资源
    最近更新 更多