Если f
дорого и не векторизуемо, вы можете использовать np.tri
и друзей в соответствии с
>>> import numpy as np
>>> from operator import itemgetter as iget
>>>
# set up an example
>>> a1, b1 = 'a1', 'b1'
>>> a, b, c, k, l = np.random.randint(0, 10, (5, 3))
>>> dic = {a1: [a,b,c], b1: [b,k,l]}
>>> f = np.dot
>>>
# do the computation
>>> RES = {}
>>> for k, v in dic.items():
... N = len(v)
... res = np.ones((N, N))
... I, J = np.triu_indices_from(res, 1)
... res[I, J] = np.fromiter(map(f, iget(*I.tolist())(v), iget(*J.tolist())(v)), float, N*(N-1)//2)
... np.copyto(res, res.T, where=np.tri(*res.shape, -1, bool))
... RES[k] = res
...
# check
>>> RES
{'a1': array([[ 1., 108., 122.],
[108., 1., 120.],
[122., 120., 1.]]), 'b1': array([[ 1., 42., 66.],
[42., 1., 20.],
[66., 20., 1.]])}
Вместо map(f, iget(...
вы также можете использовать itertools.starmap(f, itertools.combinations(v, 2))
.