元组列表上的集合论魔法

2024-09-29 17:13:34 发布

您现在位置:Python中文网/ 问答频道 /正文

在python中,我有两个列表A和{}。两个列表都由元组(x,y)组成。例如:

A = [('x1','y1'), ('x2','y2'), ('x3','y3')]
B = [('x1','y1'), ('x2','y5'), ('x4','y4')]

现在,我想要三个结果。只要不涉及元组,所有这些问题都可以用集合论很容易地求解。在

结果1:两个列表的交集:set(A) & set(B))。所以结果应该是比较两个列表元组的两个值。结果应该是:C = [('x1','y1')]

结果2:只有(x,y)[0]匹配的两个列表相交。结果应该是:D = (('x1','y1'), ('x2', ('y2', 'y5'))]。理想的解决方案是D - C -> E = [('x2', ('y2', 'y5'))],但我可以接受D本身。在

结果3:列表BA的唯一性:set(B)-(set(A) & set(B))。仅在(x,y)[0]上比较。结果应该是:[('x4', 'y4')]。在

我在这些问题上找不到任何东西,也无法自己想出解决办法。有人能帮忙吗?在


Tags: 列表解决方案元组x1x2set理想y1
3条回答

下面是一些使用dicts做你想做的事情的方法。这是python2代码;它需要对python3进行一些小的修改。IIRC,python3没有dict.iteritems(),因为它的dict.items()返回的是迭代器而不是列表。在

A = [('x1','y1'), ('x2','y2'), ('x3','y3')]
B = [('x1','y1'), ('x2','y5'), ('x4','y4')]

dA = dict(A)
dB = dict(B)

#Intersection, the simple way
print 'Result 1a:', list(set(A) & set(B))

#Intersection using dicts instead of sets
result = [(k, vA) for k, vA in dA.iteritems() if dB.get(k) == vA]
print 'Result 1b:', result

#match on 1st tuple element, ignoring 2nd element
result = {}
for k, vA in dA.iteritems():
    vB = dB.get(k)
    if vB:
        result[k] = (vA, vB) if vB != vA else vA
print 'Result 2a:', result.items()

#match on 1st tuple element only if 2nd elements don't match
result = {}
for k, vA in dA.iteritems():
    vB = dB.get(k)
    if vB and vB != vA:
        result[k] = (vA, vB)
print 'Result 2b:', result.items()

#unique elements of B, ignoring 2nd element
result = [(k, vB) for k, vB in dB.iteritems() if k not in dA]
print 'Result  3:', result

输出

^{pr2}$

为什么不使用python的set()?1是非常直接的,2是需要更多的工作:

A = [('x1','y1'), ('x2','y2'), ('x3','y3')]
B = [('x1','y1'), ('x2','y5'), ('x4','y4')]

a,b = set(A),set(B)
print '1:',a&b

axs = set(map(itemgetter(0),A))
bxs = set(map(itemgetter(0),B))

result2 = []
for c in axs&bxs:
    result2.append((c,set([y for x,y in A+B if x==c]))
print '2:',result2

输出:

^{pr2}$

你可以用一个非常相似的方法来处理3

  1. 两个列表的交集:

    您已经知道解决方案:set(A) & set(B)。或者,等价地,set(A).intersection(B)。在

    >>> A = [('x1', 'y1'), ('x2', 'y2'), ('x3', 'y3')]
    >>> B = [('x1', 'y1'), ('x2', 'y5'), ('x4', 'y4')]
    >>> set(A).intersection(B)
    {('x1', 'y1')}
    
  2. 只有(x,y)[0]匹配的两个列表的交集:

    首先,确保A和{}都按它们的x坐标排序。在

    然后使用itertools.groupby()和字典:

    ^{pr2}$

    (这和你问的不太一样,因为,正如你所见,我们用('x1', {'y1'})而不是{}。另外,我们有集合而不是列表,但这两个问题都是很容易修复的。)

    如果要排除公共点:请在调用groupby()之前从AB中删除它们:

    >>> A = set(A)
    >>> B = set(B)
    >>> common_points = A & B
    >>> A = [point for point in A if point not in common_points]
    >>> B = [point for point in B if point not in common_points]
    
  3. 列表BA的唯一性,仅在(x,y)[0]上比较:

    构造A中所有点的x坐标集:

    >>> exclude = {point[0] for point in A}
    >>> [point for point in B if point[0] not in exclude]
    [('x4', 'y4')]
    

    注意,exclude的元素是a_grouped的键,这意味着您可以重用上一个问题中的部分代码并编写:

    >>> [point for point in B if point[0] not in a_grouped]
    [('x4', 'y4')]
    

对于所有这些解决方案,性能和可读性都可以提高,如果您要使用我的代码,请考虑这一点。在

相关问题 更多 >

    热门问题