遍历列表中的每两个元素[重复]

2024-11-29 08:41:00
admin
原创
176
摘要:问题描述:如何进行for循环或列表推导以便每次迭代都给我两个元素?l = [1,2,3,4,5,6] for i,k in ???: print str(i), '+', str(k), '=', str(i+k) 输出:1+2=3 3+4=7 5+6=11 解决方案 1:您需要一个pairwise...

问题描述:

如何进行for循环或列表推导以便每次迭代都给我两个元素?

l = [1,2,3,4,5,6]

for i,k in ???:
    print str(i), '+', str(k), '=', str(i+k)

输出:

1+2=3
3+4=7
5+6=11

解决方案 1:

您需要一个pairwise()(或grouped())实现。

def pairwise(iterable):
    "s -> (s0, s1), (s2, s3), (s4, s5), ..."
    a = iter(iterable)
    return zip(a, a)

for x, y in pairwise(l):
   print("%d + %d = %d" % (x, y, x + y))

或者更一般地:

def grouped(iterable, n):
    "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
    return zip(*[iter(iterable)]*n)

for x, y in grouped(l, 2):
   print("%d + %d = %d" % (x, y, x + y))

在 Python 2 中,您应该导入它izip来替代 Python 3 的内置zip()函数。

非常感谢马丁诺 (martineau)回答了我的问题,我发现这种方法非常有效,因为它只在列表中迭代一次,并且不会在此过程中创建任何不必要的列表。

注意:这不应与Python 自己的文档中的pairwise配方相混淆,其结果是,正如@lazyr在评论中指出的那样。itertoolss -> (s0, s1), (s1, s2), (s2, s3), ...

对于那些想要在 Python 3 上使用mypy进行类型检查的人来说,这里有一些补充:

from typing import Iterable, Tuple, TypeVar

T = TypeVar("T")

def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
    """s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
    return zip(*[iter(iterable)] * n)

解决方案 2:

嗯,你需要 2 个元素的元组,所以

data = [1,2,3,4,5,6]
for i,k in zip(data[0::2], data[1::2]):
    print str(i), '+', str(k), '=', str(i+k)

在哪里:

  • data[0::2]意味着创建元素的子集(index % 2 == 0)

  • zip(x,y)从 x 和 y 集合相同的索引元素创建一个元组集合。

解决方案 3:

>>> l = [1,2,3,4,5,6]

>>> zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

>>> zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]

>>> [a+b for a,b in zip(l,l[1:])[::2]]
[3, 7, 11]

>>> ["%d + %d = %d" % (a,b,a+b) for a,b in zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']

解决方案 4:

一个简单的解决方案。

l = [1, 2, 3, 4, 5, 6]

对于 i 在范围内(0,len(l),2):
    打印 str(l[i]), '+', str(l[i + 1]), '=', str(l[i] + l[i + 1])

解决方案 5:

虽然所有使用的答案zip都是正确的,但我发现自己实现该功能可以使代码更具可读性:

def pairwise(it):
    it = iter(it)
    while True:
        try:
            yield next(it), next(it)
        except StopIteration:
            # no more elements in the iterator
            return

it = iter(it)部分确保它it实际上是一个迭代器,而不仅仅是一个可迭代对象。如果it已经是一个迭代器,则此行是无操作。

用法:

for a, b in pairwise([0, 1, 2, 3, 4, 5]):
    print(a + b)

解决方案 6:

我希望这将是一种更加优雅的方法。

a = [1,2,3,4,5,6]
zip(a[::2], a[1::2])

[(1, 2), (3, 4), (5, 6)]

解决方案 7:

如果您对性能感兴趣,我做了一个小的基准测试(使用我的库simple_benchmark)来比较解决方案的性能,并且我从我的一个包中包含了一个功能:iteration_utilities.grouper

from iteration_utilities import grouper
import matplotlib as mpl
from simple_benchmark import BenchmarkBuilder

bench = BenchmarkBuilder()

@bench.add_function()
def Johnsyweb(l):
    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return zip(a, a)

    for x, y in pairwise(l):
        pass

@bench.add_function()
def Margus(data):
    for i, k in zip(data[0::2], data[1::2]):
        pass

@bench.add_function()
def pyanon(l):
    list(zip(l,l[1:]))[::2]

@bench.add_function()
def taskinoor(l):
    for i in range(0, len(l), 2):
        l[i], l[i+1]

@bench.add_function()
def mic_e(it):
    def pairwise(it):
        it = iter(it)
        while True:
            try:
                yield next(it), next(it)
            except StopIteration:
                return

    for a, b in pairwise(it):
        pass

@bench.add_function()
def MSeifert(it):
    for item1, item2 in grouper(it, 2):
        pass

bench.use_random_lists_as_arguments(sizes=[2**i for i in range(1, 20)])
benchmark_result = bench.run()
mpl.rcParams['figure.figsize'] = (8, 10)
benchmark_result.plot_both(relative_to=MSeifert)

在此处输入图片描述

因此,如果您想要最快的解决方案而不需要外部依赖,那么您可能应该只使用 Johnysweb 提供的方法(在撰写本文时,它是最受支持和接受的答案)。

如果您不介意额外的依赖,那么速度grouper可能iteration_utilities会更快一些。

额外的想法

有些方法有一些限制,这里还未讨论。

例如,一些解决方案仅适用于序列(即列表、字符串等),例如使用索引的 Margus/pyanon/taskinoor 解决方案,而其他解决方案适用于任何可迭代对象(即序列生成器、迭代器),如 Johnysweb/mic_e/my 解决方案。

然后 Johnysweb 还提供了一个适用于 2 以外其他尺寸的解决方案,而其他答案则不行(好的,iteration_utilities.grouper还允许将元素数量设置为“组”)。

然后还有一个问题,如果列表中元素的数量为奇数,会发生什么情况。是否应该忽略剩余项?是否应该填充列表以使其大小均匀?是否应该将剩余项作为单个返回?其他答案没有直接解决这一点,但是,如果我没有忽略任何内容,它们都遵循应忽略剩余项的方法(taskinoors 答案除外 - 这实际上会引发异常)。

grouper可以决定你想做什么:

>>> from iteration_utilities import grouper

>>> list(grouper([1, 2, 3], 2))  # as single
[(1, 2), (3,)]

>>> list(grouper([1, 2, 3], 2, truncate=True))  # ignored
[(1, 2)]

>>> list(grouper([1, 2, 3], 2, fillvalue=None))  # padded
[(1, 2), (3, None)]

解决方案 8:

结合使用zipiter命令:

我发现这个解决方案iter非常优雅:

it = iter(l)
list(zip(it, it))
# [(1, 2), (3, 4), (5, 6)]

我在Python 3 zip 文档中找到了它。

it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in zip(it, it)), sep='
')

# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11

N一次概括所有元素:

N = 2
list(zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]

解决方案 9:

for (i, k) in zip(l[::2], l[1::2]):
    print i, "+", k, "=", i+k

zip(*iterable)返回一个包含每个可迭代对象的下一个元素的元组。

l[::2]返回列表的第 1 个、第 3 个、第 5 个等元素:第一个冒号表示切片从头开始,因为它后面没有数字,第二个冒号只有在您想要“切片中的步骤”时才需要(在本例中为 2)。

l[1::2]执行相同的操作,但从列表的第二个元素开始,因此它返回原始列表的第 2、第 4、第 6 等元素。

解决方案 10:

有很多方法可以做到这一点。例如:

lst = [1,2,3,4,5,6]
[(lst[i], lst[i+1]) for i,_ in enumerate(lst[:-1])]    
>>>[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

list(zip(*[iter(lst)]*2))
>>>[(1, 2), (3, 4), (5, 6)]

解决方案 11:

解包后:

l = [1,2,3,4,5,6]
while l:
    i, k, *l = l
    print(f'{i}+{k}={i+k}') 

注意:这将消耗l,之后将其留空。

解决方案 12:

您可以使用more_itertools包。

import more_itertools

lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
    print(f'{i} + {j} = {i+j}')

解决方案 13:

对于任何人来说,它都可能有所帮助,这是一个类似问题的解决方案,但具有重叠对(而不是互斥对)。

来自 Python itertools 文档:

from itertools import izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

或者更一般地:

from itertools import izip

def groupwise(iterable, n=2):
    "s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
    t = tee(iterable, n)
    for i in range(1, n):
        for j in range(0, i):
            next(t[i], None)
    return izip(*t)

解决方案 14:

这个问题的标题具有误导性,你似乎正在寻找连续的对,但如果你想遍历所有可能对的集合,那么这将起作用:

for i,v in enumerate(items[:-1]):
        for u in items[i+1:]:

解决方案 15:

一种简单的方法:

[(a[i],a[i+1]) for i in range(0,len(a),2)]

如果您的数组是 a 并且您想按对对其进行迭代,这将非常有用。要对三元组或更多元组进行迭代,只需更改“range”步骤命令,例如:

[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]

(如果数组长度和步长不合适,则必须处理多余的值)

解决方案 16:

itertools 完善的 Python3 解决方案在以下其中一个配方中给出:

import itertools

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.zip_longest(*args, fillvalue=fillvalue)

解决方案 17:

再次尝试更清洁的解决方案

def grouped(itr, n=2):
    itr = iter(itr)
    end = object()
    while True:
        vals = tuple(next(itr, end) for _ in range(n))
        if vals[-1] is end:
            return
        yield vals

更多自定义选项

from collections.abc import Sized

def grouped(itr, n=2, /, truncate=True, fillvalue=None, strict=False, nofill=False):
    if strict:
        if isinstance(itr, Sized):
            if len(itr) % n != 0:
                raise ValueError(f"{len(itr)=} is not divisible by {n=}")
    itr = iter(itr)
    end = object()
    while True:
        vals = tuple(next(itr, end) for _ in range(n))
        if vals[-1] is end:
            if vals[0] is end:
                return
            if strict:
                raise ValueError("found extra stuff in iterable")
            if nofill:
                yield tuple(v for v in vals if v is not end)
                return
            if truncate:
                return
            yield tuple(v if v is not end else fillvalue for v in vals)
            return
        yield vals

解决方案 18:

认为这是一个分享我对 n>2 的概括的好地方,它只是一个可迭代的滑动窗口:

def sliding_window(iterable, n):
    its = [ itertools.islice(iter, i, None) 
            for i, iter
            in enumerate(itertools.tee(iterable, n)) ]                               

    return itertools.izip(*its)

解决方案 19:

我需要用一个数字来划分一个列表,然后像这样固定。

l = [1,2,3,4,5,6]

def divideByN(data, n):
        return [data[i*n : (i+1)*n] for i in range(len(data)//n)]  

>>> print(divideByN(l,2))
[[1, 2], [3, 4], [5, 6]]

>>> print(divideByN(l,3))
[[1, 2, 3], [4, 5, 6]]

解决方案 20:

使用类型,以便您可以使用mypy静态分析工具验证数据:

from typing import Iterator, Any, Iterable, TypeVar, Tuple

T_ = TypeVar('T_')
Pairs_Iter = Iterator[Tuple[T_, T_]]

def legs(iterable: Iterator[T_]) -> Pairs_Iter:
    begin = next(iterable)
    for end in iterable:
        yield begin, end
        begin = end

解决方案 21:

这里我们可以有alt_elem适合你的 for 循环的方法。

def alt_elem(list, index=2):
    for i, elem in enumerate(list, start=1):
        if not i % index:
           yield tuple(list[i-index:i])


a = range(10)
for index in [2, 3, 4]:
    print("With index: {0}".format(index))
    for i in alt_elem(a, index):
       print(i)

输出:

With index: 2
(0, 1)
(2, 3)
(4, 5)
(6, 7)
(8, 9)
With index: 3
(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
With index: 4
(0, 1, 2, 3)
(4, 5, 6, 7)

注意:考虑到在函数中执行的操作,上述解决方案可能效率不高。

解决方案 22:

这是一个简单的解决方案,即使用范围函数从元素列表中选择替代元素。

注意:这仅对偶数列表有效。

a_list = [1, 2, 3, 4, 5, 6]
empty_list = [] 
for i in range(0, len(a_list), 2):
    empty_list.append(a_list[i] + a_list[i + 1])   
print(empty_list)
# [3, 7, 11]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3998  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2749  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   85  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   96  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   83  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用