【问题标题】:Negative bounds slice负边界切片
【发布时间】:2016-03-30 20:12:57
【问题描述】:

我有两个长度为 n 的元组,我需要检查除了位置 w 的元素之外,相同位置的所有元素是否相同。这是我写的:

if all(tup1[i] == tup2[i] for i in xrange(n) if i != w):
    ...

为了避免循环(因为这段代码会被多次使用),我尝试使用切片。不幸的是,这不起作用:

if tup1[w-1:w-n:-1] == tup2[w-1:w-n:-1]:
    ...

我有义务写这样的东西吗?

if tup1[:w-1] == tup2[:w-1] and tup1[w+1:] == tup2[w+1:]

难道没有更优雅的方法吗?

或者循环和切片都不好,有更好的方法来获得我正在寻找的结果吗? (我不能使用过滤器,因为可能存在与 w 位置的元素具有相同值的元素)

【问题讨论】:

  • all 方法会更好,因为当您切片元组时,您将通过迭代它们来创建原始元组的副本。但是当你使用all时,如果两个元素不同,则元组的其余部分根本不会被迭代。
  • 这绝对是过早优化的情况。您试图以每次复制整个列表为代价来迭代 n-1 项(可忽略的优化)!在分析告诉您存在问题之前不要进行优化。
  • 确实,这甚至没有嵌套循环。均衡两个可迭代对象和执行 for 循环检查所需的复杂性都是线性的。因此不需要优化。

标签: python tuples slice negative-number


【解决方案1】:

我认为您已经找到了最佳解决方案:

 tup1[:w-1] == tup2[:w-1] and tup1[w+1:] == tup2[w+1:]

如果元组非常长并且您不想复制数据并且想要提前退出行为,那么使用 itertoolsoperator em>:

>>> from operator import eq
>>> from itertools import imap
>>> w = 5
>>> t1 = (10, 20, 30, 40, -1, 50, 60, 70)
>>> t2 = (10, 20, 30, 40, -1, 50, 60, 70)
>>> it1, it2 = iter(t1), iter(t2)
>>> all(imap(eq, islice(it1, w-1), islice(it2, w-1))) \
    and (next(it1, True) or True) and (next(it2, True) and True) \
    and all(imap(eq, it1, it2))
True

这需要大量的设置工作,并且逐步不像元组切片那样快,但它确实避免了复制所有数据并且确实有一个提前退出。

在非极端情况下,我会坚持你的双切片元组平等解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    相关资源
    最近更新 更多