Python - 使用嵌套列表进行数学运算

4
如果我有一个嵌套列表,例如x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]],我该如何计算它们之间的差异?我们称x中的列表为A、B和C。我想计算A与B&C之间的差异,然后计算B与A&C之间的差异,然后计算C与A&B之间的差异,并将它们放入一个列表diff = []中。 我的问题在于正确索引数字,并使用它们对其他列表中的相应元素进行数学计算。 到目前为止,我所拥有的是:
for i in range(len(x)):
diff = [] 
    for j in range(len(x)):
        if x[i]!=x[j]:
            a = x[i]
            b = x[j]
            for h in range(len(a)):
                d = a[h] - b[h]
                diff.append(d)

基本上,A和B之间的差异是([1-2] + [2-4] + [3-6])
我希望它返回:diff = [[diff(A,B), diff(A,C)], [diff(B,A), diff(B,C)], [diff(C,A), diff(C,B)]],并且正确计算出点之间的差异。
谢谢!

2
你可能想要使用numpy来完成这个任务。例如:import numpy as np; np.array([1,2,3]) - np.array([2,4,6]) - Alexander L. Hayes
那么,diff([1, 2, 3], [2, 4, 6]) 表示的是 1-2 + 2-4 + 3-6 而不是 [1-2, 2-4, 3-6]?在这个问题中,diff(A,B) 实际上代表什么? - jarmod
4个回答

2
这是一个需要了解一些Python标准库的问题 - 特别是 itertools
举个例子,要获取你想操作的列表对,可以使用itertools.permutations
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
list(permutations(x, r=2))

这将为您提供所需的列表对:

[([1, 2, 3], [2, 4, 6]),
 ([1, 2, 3], [3, 5, 7]),
 ([2, 4, 6], [1, 2, 3]),
 ([2, 4, 6], [3, 5, 7]),
 ([3, 5, 7], [1, 2, 3]),
 ([3, 5, 7], [2, 4, 6])]

现在,如果你可以按每对的第一个进行分组...itertools.groupby正好可以实现这一点。

x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
list(list(g) for k, g in groupby(permutations(x, r=2), key=lambda p: p[0]))

这将生成一个按第一个元素分组的列表列表:

[[([1, 2, 3], [2, 4, 6]), ([1, 2, 3], [3, 5, 7])],
 [([2, 4, 6], [1, 2, 3]), ([2, 4, 6], [3, 5, 7])],
 [([3, 5, 7], [1, 2, 3]), ([3, 5, 7], [2, 4, 6])]]

把所有东西放在一起,你可以编写一个简单的函数,以你想要的方式减去列表,并将每个对传递进去:
from itertools import permutations, groupby

def sum_diff(pairs):
    return [sum(p - q for p, q in zip(*pair)) for pair in pairs]
    
x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]

# call sum_diff for each group of pairs
result = [sum_diff(g) for k, g in groupby(permutations(x, r=2), key=lambda p: p[0])]

# [[-6, -9], [6, -3], [9, 3]]

这样做可以将问题简化为只需几行代码,并且对于大型列表的性能也很好。而且,由于您提到了保持索引的困难,注意这段代码除了选择第一个元素进行分组之外,没有使用任何索引。


1
这正是我正在努力寻找的答案。恭喜你先到达并且比我更好地解释了它! - Chris

2
你的解决方案实际上并不那么遥远。正如Aniketh所提到的,一个问题是你使用了x[i] != x[j]。由于x[i]x[j]都是数组,这将始终评估为false。
原因是Python默认情况下不会对数组进行有用的比较。它只会检查数组引用是否相同。这显然不是你想要的,你试图看看数组在x中是否处于相同的索引位置。为此,请使用i != j
虽然这里发布了其他解决方案,但我会添加我的解决方案,因为我已经写了它。它利用了Python的列表理解。
def pairwise_diff(x):
    diff = []
    for i in range(len(x)):
        A = x[i]
        for j in range(len(x)):
            if i != j:
                B = x[j]
                assert len(A) == len(B)
                item_diff = [A[i] - B[i] for i in range(len(A))]
                diff.append(sum(item_diff))

    # Take the answers and group them into arrays of length 2
    return [diff[i : i + 2] for i in range(0, len(diff), 2)]


x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
print(pairwise_diff(x))

1
这里是我认为你正在寻找的代码。下面我会对它进行解释:
def diff(a, b):
  total = 0
  for i in range(len(a)):
    total += a[i] - b[i]
  return total

x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
  
differences = []
for i in range(len(x)):
  soloDiff = []
  for j in range(len(x)):
    if i != j:
      soloDiff.append(diff(x[i],x[j]))
  differences.append(soloDiff)

print(differences)

输出:

[[-6, -9], [6, -3], [9, 3]]

首先,在您解释算法时,您明确指出应使用函数计算两个列表之间的差异,因为您将重复使用它。

您的for循环开始得很好,但您应该有第二个列表将diff附加到3次。此外,在检查重复项时,您需要确保i! = j,而不是x [i]!= x [j]

如果您有其他问题,请告诉我!!


1
这是我能想到的最简单的解决方案:

import numpy as np

x = [[1, 2, 3], [2, 4, 6], [3, 5, 7]]
x = np.array(x)
vectors = ['A','B','C']
for j in range(3):
    for k in range(3):
        if j!=k:
            print(vectors[j],'-',vectors[k],'=', x[j]-x[k])

这将返回

A - B = [-1 -2 -3]
A - C = [-2 -3 -4]
B - A = [1 2 3]
B - C = [-1 -1 -1]
C - A = [2 3 4]
C - B = [1 1 1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接