python – 检查两个嵌套列表在替换时是否相同

在某些情况下,我试图列举在计算四个玩家的Banzhaf power indices时可能发生的独特情况的数量,当没有*者并且有四个或五个获胜联盟时.

我使用以下代码生成一组我想要迭代的列表.

from itertools import chain, combinations

def powerset(iterable):
    s = list(iterable)
    return chain.from_iterable(map(list, combinations(s, r)) for r in range(2, len(s)+1))

def superpowerset(iterable):
    s = powerset(iterable)
    return chain.from_iterable(map(list, combinations(s, r)) for r in range(4, 6))

set_of_lists = superpowerset([1,2,3,4])

但是,如果在重映射中它们是等效的,则此集合中的两个列表不应被视为唯一.

使用以下列表作为示例:

[[1, 2], [1, 3], [2, 3], [1, 2, 4]]

如果每个元素2重命名为3,反之亦然,我们将获得:

[[1, 3], [1, 2], [3, 2], [1, 3, 4]]

每个子列表中的顺序并不重要,子列表的顺序也不重要.因此,交换列表可以重写为:

[[1, 2], [1, 3], [2, 3], [1, 3, 4]]

有4个值,因此可能发生P(4,4)= 24个可能的重映射(包括平凡映射).

有没有办法轻松检查?或者,更好的是,是否有办法避免生成这些列表?

我甚至不确定如何将第一个列表转换为第二个列表(但是可以从那里强制它).另外,我不限于数据类型(在某种程度上),使用freezeset也没关系.

编辑:tobias_k提供的解决方案回答了“检查”问题,但正如评论中所述,我认为我对这个问题采取了错误的方法.

解决方法:

这可能还没有完整的解决方案,但它可能会向您展示进一步调查的方向.

您可以将每个元素映射到有关“拓扑”的某些特征,以及它与其他元素的“连接”.你必须小心不要考虑集合中的顺序,或者 – 显然 – 元素本身.例如,您可以考虑元素出现的频率,它出现在哪个大小的组中,以及类似的东西.将这些指标与关键函数组合,按该键对元素进行排序,并按顺序为它们分配新名称.

def normalize(lists):
    items = set(x for y in lists for x in y)
    counter = itertools.count()
    sorter = lambda x: sorted(len(y) for y in lists if x in y)
    mapping = {k: next(counter) for k in sorted(items, key=sorter)}
    return tuple(sorted(tuple(sorted(mapping[x] for x in y)) for y in lists))

这会将您的两个示例列表映射到相同的“规范化”列表:

>>> normalize([[1, 2], [1, 3], [2, 3], [1, 2, 4]])
((0, 1), (0, 2), (1, 2), (1, 2, 3))
>>> normalize([[1, 3], [1, 2], [3, 2], [1, 3, 4]])
((0, 1), (0, 2), (1, 2), (1, 2, 3))

当应用于所有列表时,它会将计数从330减少到36.我不知道这是否是最小的,但它看起来是一个好的开始.

>>> normalized = set(map(normalize, set_of_lists))
>>> len(normalized)
36
上一篇:生成字符串中所有可能的字符组合


下一篇:python-itertools.product是否懒惰地评估其参数?