【问题标题】:How to subtract one from every value in a tuple in Python?如何从 Python 元组中的每个值中减去一个?
【发布时间】:2013-01-29 14:27:56
【问题描述】:

我有一个用zip() 创建的元组,我需要从元组中的每个整数中减去一个。我尝试了以下方法,但显然它只适用于列表,那么我如何将它用于 Python 中的元组?

[...]
lower, upper = zip(*table)
lower[:] = [x + 1 for x in lower]
upper[:] = [x - 1 for x in upper]
holes = zip(lower[:-1], upper[1:])

TypeError: 'tuple' 对象不支持项目分配

大图是我在table 中存储了一系列不重叠的排序间隔,我需要获取一系列孔。例如。我的间隔表可能是:

[ 6,  7]
[ 8,  9]
[14, 18]
[23, 32]

我想计算间隔之间的holes

[10, 13]
[19, 22]

【问题讨论】:

  • 在@gnibbler 的帮助下进行了许多推理,并对我的代码进行了多次编辑,最终我得到了一个最终的结果。请看它,并告诉我你的想法。
  • @eyquem 为了改进您的答案,我将编辑您如何得出答案的评论,以使答案简短而甜蜜。

标签: python integer tuples


【解决方案1】:

tuple 构造函数与生成器表达式一起使用:

lower = tuple(x - 1 for x in lower)
upper = tuple(x + 1 for x in upper)

【讨论】:

  • 为了提供 OP 所需的结果,必须以这种方式更改运算符和切片:holes = zip([x + 1 for x in upper][:-1], [x - 1 for x in lower][1:])
  • 是的,你可以在一行中完成,但我认为它看起来更干净,分成多行。 (这只是我的看法)。
  • sorry nneonneo 我的评论与返回预期答案有关,而不是放在一行中(这只是为了方便,只是一个评论)。我编辑了我的评论以澄清这方面(另见 ogzd 评论)
  • @nneonneo @furins 在zip([x + 1 for x in upper][:-1], 之后单击 ENTER 将使该套件出现在下一行(对 nneonneo 来说很高兴),而它本质上仍然是单行(对 furins 来说很高兴)
【解决方案2】:

您也可以在单个列表理解中解决这些问题:

holes = [(table[i][1]+1, table[i+1][0]-1) for i in range(len(table)-1)]

【讨论】:

  • 啊我写了同一行,但忘了他想删除lower的第一个元素和upper的最后一个元素。我认为这个解决方案更像 pythonic。
  • @ogzd,是的,这似乎是现在想要的,现在有一个例子
  • 更准确地说,答案应该是holes = zip([x + 1 for x in upper][:-1], [x - 1 for x in lower][1:])(列表列表)以匹配给定的示例...;)
  • @gnibbler 你好,gnibbler,你看到我的回答了吗?我想知道您对此有何看法。
【解决方案3】:

使用生成器函数可以轻松完成任务。

table = [(2,3),(5,6),(12,20),(21,25),(28,28),(35,48),(53,55)]

def gaps_between(intervals):
    prec = intervals[0][1] + 1
    for L,H in intervals:
        print '\nprec = %d   (L,H) = (%d,%d)' % (prec,L,H)
        print 'prec = %d <= L-1 = %d : %s' % (prec,L-1,prec<=L)
        if prec<=L-1:
            yield (prec,L-1)
        prec = H + 1
        print 'next prec = %d' % prec

holes = list(gaps_between(table))

print
print 'table =',table
print 'holes =',holes 

在以前的答案中,我使用了在生成器中定义的迭代器。
为了避免这种情况,我在上面使用了一个策略:
定义first prec = first H = intervals[0][1].
鉴于每对 (L,H) 对 H&gt;=L ,它导致
first H &gt; first L - 1 --> first prec &gt; first L - 1
因此,关于第一个区间的第一个测试总是 False,真正的过程从第二个区间开始。

prec = 3   (L,H) = (2,3)
prec = 3 <= L-1 = 1 : False
next prec = 4

prec = 4   (L,H) = (5,6)
prec = 4 <= L-1 = 4 : True
next prec = 7

prec = 7   (L,H) = (12,20)
prec = 7 <= L-1 = 11 : True
next prec = 21

prec = 21   (L,H) = (21,25)
prec = 21 <= L-1 = 20 : True
next prec = 26

prec = 26   (L,H) = (28,28)
prec = 26 <= L-1 = 27 : True
next prec = 29

prec = 29   (L,H) = (35,48)
prec = 29 <= L-1 = 34 : True
next prec = 49

prec = 49   (L,H) = (53,55)
prec = 49 <= L-1 = 52 : True
next prec = 56

table = [(2, 3), (5, 6), (12, 20), (21, 25), (28, 28), (35, 48), (53, 55)]
holes = [(4, 4), (7, 11), (26, 27), (29, 34), (49, 52)]

结果正确:
- 它给出了 (2,3) 和 (5,6) 之间的间隙 (4,4)
- (12,20) 和 (21,25) 之间没有差距
- (28,28) 中的值 28 没有任何间隙

OP 表示间隔不重叠且已排序。
但是,测试if prec&lt;=L-1 是强制性的,否则连续间隔会出错:
如果没有这个测试,结果将包含
....., (7, 11), (21, 20), (26, 27), .......

碰巧通​​过这个强制测试,以下间隔列表
[[ 8, 9],[14, 18],[18, 32]]
[[8, 9], [14, 18], [19, 20], [16, 21], [23, 32]]
重叠的(不是 OP 所说的)
如果没有测试,那会出错,
实际上不会产生任何错误。

使用我上面的代码给出正确间隔列表的间隔列表的规则是间隔必须沿着第二个元素排序。

.

yield (prec,L-1) 替换为yield range(prec,L) 会将间隙作为范围。

例如,将yield (prec,L-1) 替换为holes.append((prec,L-1)) 允许编写没有函数的代码。

【讨论】:

  • 在生成器中存储prec 是一个很好的可读解决方案。您不需要else 子句,只需将prec = b 移动到if 块之后。 OP 现在表示这些对已排序且不重叠,因此您无需针对这些情况进行测试。但我认为,如果可能出现,从输出中抑制 (4, 4) 和 (22, 22) 之类的“空洞”可能是有意义的。
  • 啊!你是对的线prec = b。如果prec = b + 1 也可以删除指令a += 1b += 1。 - 但是对于 (4,4) 和 (22,22),它是正确的:它们意味着只有一个数字的差距。 - 我想象了其他解决方案,基于输出直接是范围。 - 感谢您的评论
  • 如果你想避免修改表,一种方法是最初设置prec = None并在循环中测试它
  • 你是对的,只有一个条目。对于一个空洞,桌子看起来像[[16, 21], [22, 32]],而洞看起来像[22, 21]
  • @gnibbler raaaaa.... 经过多次编辑,我终于得到了最终答案。我没有保留您使用None 的想法,因为比较None 和数字不起作用,而且我不想添加仅在第一步有用的测试。我得到了初始化 first prec = intervals[0][1] == first H 的想法,它总是严格优于第一个值 intervals[0][0] - 1 == first L -1 因为 LH 总是这样 H &gt;= L 然后 first H &gt; first L-1 ,然后是 first prec &gt; first L-1 然后 first prec &lt;= first L -1 是总是假的。
猜你喜欢
  • 2015-09-08
  • 1970-01-01
  • 2022-09-23
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多