python - 如何获取两个列表之间的所有唯一分配

标签 python list combinatorics

我有两个列表,每个列表都可以包含重复的值,但任何值只能出现在这两个列表之一(或没有)中。

A = [0,1]
B = [2,3]

我想获取这两个列表之间的所有唯一映射。

assignment(A,B) = [((0,2),(1,3)), ((0,3),(1,2))]

我知道这可以通过使用 itertools.permutations 来完成。 然而,两个列表中的一个/两个都可能有重复项,然后这种方法会给我重复项,因为我不关心分配的顺序。因为对于每个可能的任务,我只想找到总距离。

A = [1,1]
B = [2,3]
mapping(A,B) = [((1,2),(1,3)), ((1,3),(1,2))]

期望的输出是

mapping(A,B) = [((1,2),(1,3))]

如果只有第一个列表重复,我可以使用 sympy.utilities.iterables.multiset_permutations 来实现这一点。虽然这对我来说也不起作用,因为它与 numba 配合不好

但是第二个列表也可能重复,即使这样我也会得到类似的结果

A = [0,1]
B = [3,3]
mapping(A,B) = [((0,3),(1,3)), ((1,3),(0,3))]

期望的输出是

mapping(A,B) = [((0,3),(1,3))]

此外,理想情况下我希望代码能够与 numba 一起使用。 我最好的方法是生成 A 的所有排列,将它们放入一组中以过滤掉重复项,然后执行评估 B 上重复选项的额外工作吗? (它不会给出错误的结果,只是会减慢代码速度)

目前我最好的猜测是我必须这样做

AB = [list(zip(perm, B)) for perm in set(permutations(A, len(B)))]

@njit
def permutations(A, k):
    """Calculates permutation of k elements in A. Needed because numba doesnt like itertools"""
    r = [[i for i in range(0)]]
    for i in range(k):
        r = [[a] + b for a in A for b in r if (a in b) == False]
    return r

并且只需对 B 具有重复项的情况进行额外的工作即可。

编辑: 我现在得到了两个版本,可以给出所需的结果:

set(tuple(sorted(zip(perm, B))) for perm in set(permutations(A, len(B))))

set(tuple(sorted(zip(A, p))) for p in permutations(B))

以及生成来自第二个数组的重复项的先前版本

[zip(perm, B) for perm in set(permutations(A, len(B)))]

我还测试了哪个版本对于我的具体用例来说是最快的:

from itertools import product, permutations
import timeit
import numpy as np
A = [0,0,1,1]
B = [2,3,3,3]
mem = np.arange(5)

def vers1(A,B,mem):
    res = float("inf")
    for mapping in set(tuple(sorted(zip(A, p))) for p in permutations(B)):
        temp = 0
        for a, b in mapping:
            temp += abs(mem[a]-mem[b])
        res = min(res,temp)
    return res
    
def vers2(A,B,mem):
    res = float("inf")
    for mapping in set(tuple(sorted(zip(perm, B))) for perm in set(permutations(A, len(B)))):
        temp = 0
        for a, b in mapping:
            temp += abs(mem[a]-mem[b])
        res = min(res,temp)
    return res
    
def vers3(A,B,mem):
    res = float("inf")
    for mapping in [zip(perm, B) for perm in set(permutations(A, len(B)))]:
        temp = 0
        for a, b in mapping:
           temp += abs(mem[a]-mem[b])
        res = min(res,temp)
    return res

print(vers1(A,B,mem))
print(timeit.timeit("vers1(A,B,mem)",'from __main__ import vers1, A, B,mem'))
print(vers2(A,B,mem))
print(timeit.timeit("vers2(A,B,mem)",'from __main__ import vers2, A, B,mem'))
print(vers3(A,B,mem))
print(timeit.timeit("vers3(A,B,mem)",'from __main__ import vers3, A, B,mem'))

得到了这个结果:

9
58.46571195700017
9
23.15174284099703
9
28.064288804998796

最佳答案

使用集合删除重复项

import itertools as it

A=[0,1]
B=[3,3]
AB = list(set(tuple(zip(A, p)) for p in it.permutations(B)))

关于python - 如何获取两个列表之间的所有唯一分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74093046/

相关文章:

python - 来自迭代器的随机项目?

python-3.x - 递归地从 N 中选择 K 个项目,直到为空

python - 如何正确使用 Selenium 抓取 Twitter 用户名?

python - 在另一列中查找具有相同值的行 - Python

python - 我的Python代码只选择了列表内容的一半?

java - 从android中的数组列表中删除重复项

python - 切片操作给我的是深拷贝还是浅拷贝?

python - 组合数学实现和难题

python - 限制正则​​表达式中的位数

python - 如何改变 Pytorch 数据集的大小?