我有一个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))]
答案 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 = ""
}