Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在列表中查找三个相反的值_Python_List_Tuples_List Comprehension - Fatal编程技术网

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

Python 在列表中查找三个相反的值,python,list,tuples,list-comprehension,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))]选择元组的规范版本;以0开头的一个或相反的一个。使用规范值作为字典中的键,以构建共享该规范值的所有元组的列表;字典的

我有一个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
开头的一个或相反的一个。使用规范值作为字典中的键,以构建共享该规范值的所有元组的列表;字典的值将成为您的成对值:

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)时间内产生输出;您只需要在输入上迭代恒定次数(1.5或2次N,取决于您是否希望首先测试正确的对)

演示:


选择元组的规范版本;以
0
开头的一个或相反的一个。使用规范值作为字典中的键,以构建共享该规范值的所有元组的列表;字典的值将成为您的成对值:

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)时间内产生输出;您只需要在输入上迭代恒定次数(1.5或2次N,取决于您是否希望首先测试正确的对)

演示:

你可以做:

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(不是t)表示tup中的t)
来创建其对立面。Its将每对存储为一个冻结集,然后获取所有这些的
,从而删除重复项。然后,它将这组集合转换回元组列表,但通过检查集合
x
和原始列表
l
的集合之间的差异是否为空集,仅保留两个值都出现在原始列表
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))]
编辑

根据Martijn Pieters的建议(见评论):

你可以做:

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(不是t)表示tup中的t)
来创建其对立面。Its将每对存储为一个冻结集,然后获取所有这些的
,从而删除重复项。然后,它将这组集合转换回元组列表,但通过检查集合
x
和原始列表
l
的集合之间的差异是否为空集,仅保留两个值都出现在原始列表
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))]
编辑

根据Martijn Pieters的建议(见评论):


那么,如果列表中没有元组的否定版本,该怎么办呢?另外,您自己也尝试过吗?在我的实现中,我知道总是有否定版本。也许对于更一般的情况,只需返回“error”,我只是想创建所有否定的版本,然后以某种方式获得唯一的元组并形成一个列表。我不是“蟒蛇主义者”,所以我想我会问。顺序重要吗?或者可以以任何顺序返回对?那么,如果列表中没有元组的否定版本,该怎么办?另外,您自己是否尝试过?在我的实现中,我知道始终存在否定版本。也许对于更一般的情况,只需返回“error”,我只是想创建所有否定的版本,然后以某种方式获得唯一的元组并形成一个列表。我不是“蟒蛇主义者”,所以我想我会问。顺序重要吗?或者可以以任何顺序返回对吗?这基本上与我的方法相同,只是做了更多的工作,可读性较差。此外,
而不是x-set(l)
每次迭代都必须创建两个新的集合。我会使用
x.issubset(l)
来避免这项繁忙的工作。后者可能更有效,因为
setl=set(l)
(循环外)和
x.issubset(l)
(循环内)。@MartijnPieters你完全正确。使用
isdisjoint
更具可读性。老实说,您使用的
元组(1-v表示t中的v)
也是如此。我将根据您的建议对此进行编辑。
isdisjoint()
实际上是错误的,您希望确保成对的两个元组都位于
l
,因此需要
issubset()
。我已经纠正了这一点。在一个完全不相关的注释中,如果你绝对确定每个元组在
l
中都有一个对应的对立面,你可以做
list(zip(sorted(l),sorted(l,reverse=True))
。这基本上和我的方法相同,只是做了更多的工作和更少的可读性。另外,
不是x-set(l)
每次迭代必须创建两个新集合。我会使用
x.issubset(l)
来避免这项繁忙的工作。后者可能更有效,因为
setl=set(l)
(循环外)和
x.issubset(l)
(循环内)。@MartijnPieters你完全正确。使用
isdisjoint
更具可读性。老实说,您使用的
元组(1-v表示t中的v)
也是如此。我将根据您的建议对此进行编辑。
isdisjoint()
实际上是错误的,您希望确保成对的两个元组都位于
l
,因此需要
issubset()
。我已经对此进行了更正。在一个完全不相关的注释中,如果您绝对确定每个元组在
l
中都有对应的对立面,那么您可以执行
列表(zip(排序(l),排序(l,reverse=True))