在列表中查找三个相反的值

时间:2016-12-10 21:55:07

标签: python list tuples list-comprehension

我有一个0或1的三元组列表。我想以pythonic的方式创建对立的元组,以便:

l = [(1, 1, 0), (1, 0, 0), (1, 0, 1), (0, 1, 0), (0, 0, 0), (1, 1, 1),(0, 1, 1),(0, 0, 1)]

变为:

new_l = [((0, 1, 1),(1, 0, 0)), ((1, 1, 0), (0, 0, 1)), ((1, 0, 1), (0, 1, 0)), ((0, 0, 0), (1, 1, 1))]

2 个答案:

答案 0 :(得分:2)

选择元组的规范版本;要么以0开头,要么以相反的那个开头。使用canonical作为字典中的键来构建共享该规范值的所有元组的列表;字典的价值成为你的对:

def canonical(t):
    return t if t[0] == 0 else tuple(1 - v for v in t)

def pair_values(l):
    paired = {}
    for t in l:
        paired.setdefault(canonical(t), []).append(t)
    if any(len(v) != 2 for v in paired.values()):
        raise ValueError("Not all tuples could be paired up")
    return [tuple(p) for p in paired.values()]

如果您100%确定元组总是可以配对,我只需完全放弃any()测试。

以上产生O(N)时间的输出;你只需要在输入上迭代几次(N或1.5倍,取决于你是否想要先测试合适的对)。

演示:

>>> # a tuple and its inversion both always produce the same canonical
... 
>>> canonical((1, 1, 0))
(0, 0, 1)
>>> canonical((0, 0, 1))
(0, 0, 1)
>>> l = [(1, 1, 0), (1, 0, 0), (1, 0, 1), (0, 1, 0), (0, 0, 0), (1, 1, 1),(0, 1, 1),(0, 0, 1)]
>>> pair_values(l)
[((1, 1, 0), (0, 0, 1)), ((1, 0, 0), (0, 1, 1)), ((1, 0, 1), (0, 1, 0)), ((0, 0, 0), (1, 1, 1))]

答案 1 :(得分:2)

你可以这样做:

new_l = [tuple(x) for x in set(frozenset([tup, tuple(int(not t) for t in tup)]) for tup in l) if not x-set(l)]

通过执行tuple(int(not t) for t in tup)获取每个值并创建相反的值。它将每一对存储为一组冻结,然后取出所有这些中的set,以消除重复。然后,它将这组集合转换回元组列表,但只保留两个值出现在原始列表l中的对,方法是检查集合x和集合l之间的差异。原始列表print(new_l) [((0, 1, 0), (1, 0, 1)), ((1, 1, 1), (0, 0, 0)), ((1, 1, 0), (0, 0, 1)), ((1, 0, 0), (0, 1, 1))] 是空集。

setl = set(l) 
new_l = [tuple(x) for x in set(frozenset([tup, tuple(1-t for t in tup)]) for tup in l) if x.issubset(setl)]

修改

与Martijn Pieters的建议(见评论):

@IBAction func btnReride(_ sender: AnyObject) {
        btnReride.text = ""
}