Python - 多个列表的成对交集,然后对所有重复项求和

Python - Pairwise intersection of multiple lists, then sum up all duplicates

a = [1,2,3]
b = [2,3,4]
c = [1,2,4]
d = [1,3,6]

大家好,

我有上面的列表,我想按以下格式显示每两个列表的成对 intersection/overlap(重复整数的数量)。任何人都知道如何实现这一目标? (任何方法都很好,但很好奇 iterative/loop 是实现此目的的唯一方法吗?)

   a  b  c  d
a  3  2  2  2
b  2  3  2  1
c  2  2  3  1
d  2  1  1  3

真正的目标对我来说更难,我需要总结每两个列表中的所有重复数字。例如,列表 a 和列表 b 在编号 2 和 3 中重复,因此我在这里需要 5。最终目标如下:

   a  b  c  d
a  6  5  3  4
b  5  9  6  3
c  3  6  7  1
d  4  3  1  10

下面是一个对 numpy 数组 X 进行成对运算的实现。这种方法假设运算是对称的以提高速度。

from itertools import combinations_with_replacement
import numpy as np

def pairwise(X, operation):        
    # Initialise precomputed matrix
    precomputed = np.zeros((X.shape[0], X.shape[0]), dtype='int')
    # Initialise iterator over objects in X
    iterator    = combinations_with_replacement(range(X.shape[0]), 2)
    # Perform the operation on each pair
    for i, j in iterator:
        precomputed[i, j] = operation(X[i], X[j])           
    # Make symmetric and return
    return precomputed + precomputed.T - np.diag(np.diag(precomputed))

我们可以定义一个函数来显示两个集合中的重叠量,并将其放入成对函数中

def overlap(x, y):
    return len(set(x) & set(y))

请注意,此解决方案需要一个 numpy 数组,因此对于您的示例,我们需要在将数据输入函数之前修改数据

X = np.array([a, b, c, d])
print(pairwise(X, overlap))

这会产生结果

[[3 2 2 2]
 [2 3 2 1]
 [2 2 3 1]
 [2 1 1 3]]

您可以将 4 个列表放入字典中,将它们转换为集合,使用 itertools.combinations_with_replacement 生成 4 个列表中 2 个之间的所有组合,将它们放入由 [=13= 索引的字典中] 键组合的值是值集的交集的长度,并在嵌套循环中打印输出:

from itertools import combinations_with_replacement
d = {'a': [1,2,3], 'b': [2,3,4], 'c': [1,2,4], 'd': [1,3,6]}
s = {frozenset([a[0], b[0]]): len(a[1] & b[1]) for a, b in combinations_with_replacement([(k, set(v)) for k, v in d.items()], 2)}
print(' ', ' '.join(d))
for i in d:
    print(i, end=' ')
    for j in d:
        print(s[frozenset([i, j])], end=' ')
    print()

这输出:

  a b c d
a 3 2 2 2 
b 2 3 2 1 
c 2 2 3 1 
d 2 1 1 3 

使用方法 np.in1d:

import numpy as np
R = []
A = np.array([a,b,c,d])
for x in A:
    A = np.array([a,b,c,d])
    ind = np.in1d(A,x).reshape(np.size(A,0),np.size(A,1))
    A[~ind] = 0
    R.append(A.sum(1))

R = np.vstack(R)

与 R:

array([[ 6,  5,  3,  4],
       [ 5,  9,  6,  3],
       [ 3,  6,  7,  1],
       [ 4,  3,  1, 10]])