Python“其他元素”成语[重复]

Posted

技术标签:

【中文标题】Python“其他元素”成语[重复]【英文标题】:Python "Every Other Element" Idiom [duplicate] 【发布时间】:2011-02-07 12:57:52 【问题描述】:

我觉得我花了很多时间用 Python 编写代码,但没有足够的时间创建 Pythonic 代码。最近我遇到了一个有趣的小问题,我认为它可能有一个简单、惯用的解决方案。套用原文,我需要收集列表中的每个连续对。例如,给定列表[1,2,3,4,5,6],我想计算[(1,2),(3,4),(5,6)]

当时我想出了一个看起来像翻译 Java 的快速解决方案。重新审视这个问题,我能做的最好的就是

l = [1,2,3,4,5,6]
[(l[2*x],l[2*x+1]) for x in range(len(l)/2)]

在长度不均匀的情况下,它具有将最后一个数字扔掉的副作用。

我是否缺少更惯用的方法,或者这是我能得到的最好的方法?

【问题讨论】:

相关的“以块为单位迭代列表的最“pythonic”方式是什么?” ***.com/questions/434287/… 【参考方案1】:

经常被引用的是:

zip(*[iter(l)] * 2)

我更喜欢iter 解决方案的这个更易读的版本:

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

【讨论】:

很糟糕,但读起来像 perl ;-) 没错,但我认为它也是迄今为止提出的最有效的解决方案。我会测试,brb。 是的,它比 RichieHindle 的解决方案快 10% 左右,因为它不需要任何内存分配,并且只需要对输入列表进行一次迭代。 知道,虽然 RichieHindle 赢得了公认的答案(真的很难忽略可读性),但这个答案赢得了我的心。 另外值得注意的是,这直接来自the Python documentation。【参考方案2】:

toolz 是一个构建良好的库,在 itertools 中忽略了许多函数式编程细节。 partition 解决了这个问题(可以选择填充奇数长度列表的最后一个条目)

>>> list(toolz.partition(2, [1,2,3,4,5,6]))
[(1, 2), (3, 4), (5, 6)]

【讨论】:

【参考方案3】:

正确的做法可能不是计算列表,而是编写一个 iterator->iterator 函数。这更通用——它适用于每个迭代,如果你想将它“冻结”成一个列表,你可以使用“list()”函数。

def groupElements(iterable, n):
    # For your case, you can hardcode n=2, but I wanted the general case here.
    # Also, you do not specify what to do if the 
    # length of the list is not divisible by 2
    # I chose here to drop such elements
    source = iter(iterable)
    while True:
        l = []
        for i in range(n):
            l.append(source.next())
        yield tuple(l)

我很惊讶 itertools 模块还没有这个功能——也许是未来的修订版。在那之前,请随意使用上面的版本:)

【讨论】:

这在性能方面怎么样?【参考方案4】:

如果您不想丢失列表中的元素,即使它们的数量没有,试试这个:

>>> l = [1, 2, 3, 4, 5]
>>> [(l[i],  l[i+1] if i+1 < len(l) else None)  for i in range(0, len(l), 2)]
[(1, 2), (3, 4), (5, None)]

【讨论】:

【参考方案5】:

试试这个

def pairs(l, n):
    return zip(*[l[i::n] for i in range(n)])

所以,

pairs([1, 2, 3, 4], 2) 给了

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

【讨论】:

【参考方案6】:

为此,我通常将itertools 文档中的grouper 配方复制到我的代码中。

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

【讨论】:

【参考方案7】:

使用range()的步进功能怎么样:

[(l[n],l[n+1]) for n in range(0,len(l),2)]

【讨论】:

【参考方案8】:

这样会更整洁一些:

>>> data = [1,2,3,4,5,6]
>>> zip(data[0::2], data[1::2])
[(1, 2), (3, 4), (5, 6)]

(但如果您不熟悉范围的“跨步”功能,它的可读性可能会降低)。

与您的代码一样,它会丢弃您具有奇数个值的最后一个值。

【讨论】:

您可以在执行上述操作之前先做一个data += [None] 来处理奇数个项目的情况。 some_list += [foo] 写成some_list.append(foo) 这个数据迭代了多少次?看看this answer

以上是关于Python“其他元素”成语[重复]的主要内容,如果未能解决你的问题,请参考以下文章

python - 分组列表元素[重复]

特殊套管最后一个元素的最佳循环成语

更改单独的元素样式以关注其他元素[重复]

悬停效果不会激活其他元素[重复]

在每个 TimeIntervalNotification 中不重复的随机元素

:hover 更改其他元素,但它也从目标触发[重复]