【问题标题】:Python Calculating Unique List Permutation PossibilitiesPython计算唯一列表排列的可能性
【发布时间】:2015-01-10 23:48:23
【问题描述】:

所以我在处理列表/字符串的排列时遇到了问题,我很难解决。

所以,假设我有几个列表:

list1 = ["a"]
list2 = ["a","b","c","d"]
list3 = ["b","e"]
list4 = ["f","g","a"]

我需要计算所有可能的排列组合的数量,同时从每个列表中选择 1 个字符。所以,从第一个列表中,我选择了一个角色。 “a”,在这种情况下,因为列表中只有一项。接下来我从第二个列表中选择一个项目,但它不能是“a”,因为它是在我之前的列表中选择的,所以它可能是“b”、“c”或“d”。接下来我从第三个列表中选择一个项目,如果我在第一个中选择“a”,在第二个中选择“b”,我只能选择“e”,因为“b”之前已经使用过。第四个列表也是如此。

所以我需要从我的列表中计算唯一字符组合的所有可能组合。希望每个人都能得到我在这里的要求。或者如果可能的话,我什至不需要创建排列列表,我只需要计算总共有 HOW MANY 组合。什么会占用更少的内存,因为实际问题中可能存在大量单独的列表

更详细地说我的问题...如果我有两个列表: list1 = [“一个”] list2 = ["b"]

只有一种组合,因为您将位置保留在置换的字符串中。列表一不包含 a b,因此唯一的组合可能是 ("a","b"),而不是 ("b","a")。为了进一步扩展这个问题的限制。我不一定要检索所有排列的结果,我只想返回可能排列的 TOTAL NUMBER。返回结果会占用太多内存,因为我将使用大约 15 个列表,每个列表中有 1 到 15 个字符。

【问题讨论】:

  • 解决 cmets 中的冲突:假设我们只有 list1 = ['a']list2 = ['b']。您希望总数为 1,因为只有 ('a','b') 作为有效选项,还是 2,因为您从 ('a','b') 开始然后置换它,得到 ('a','b'), ('b', 'a')

标签: python algorithm list unique permutation


【解决方案1】:

使用itertools.product 从列表中生成所有可能的组合。然后,使用itertools.ifilter,过滤掉所有包含重复字符的组合。一种简单的方法是检查列表的长度是否保持不变,如果您删除所有重复项(即,如果您从中创建一个集合)。

import itertools

list1 = ["a"]
list2 = ["a","b","c","d"]
list3 = ["b","e"]
list4 = ["f","g","a"]

f = lambda x: len(x) == len(set(x))
it = itertools.ifilter(f, itertools.product(list1, list2, list3, list4))

# print all combinations
for combination in it:
    print combination

【讨论】:

  • AttributeError: 'module' object has no attribute 'ifilter'
  • @howaboutNO 对于 Python 3,如果将 itertools.ifilter 替换为 filter 并在 print 行周围加上括号,则应该没问题。
  • @Carsten a,b,c,d 的排列在哪里?你的答案不正确。 OP 想要所有排列。
  • @howaboutNO: a,b,c,d 无效,因为第三个字母必须来自 list3(b 或 e,尽管此处不能是 b,因为它已经被使用过)。卡斯滕是正确的。正如 OP 所说:“接下来我从第三个列表中选择一个项目”。
  • @howaboutNO,OP 只想要你从每个列表中取出一项的烫发
【解决方案2】:

使用 itertools.product。它遍历为每个列表选择一个项目的所有排列。此外,使用列表推导来消除不符合您要求的迭代。

>>> a='a'
>>> b='abcd'
>>> c='be'
>>> d='fga'
>>> import itertools
>>> [a+b+c+d for a,b,c,d in itertools.product(a,b,c,d) if b != a and c not in [a,b] and d not in [a,b,c]]
['abef', 'abeg', 'acbf', 'acbg', 'acef', 'aceg', 'adbf', 'adbg', 'adef', 'adeg']

【讨论】:

  • ('a', 'a', 'b', 'f') 这里有两个a。这不是 OP 要求的
  • @howaboutNO 是的,没有通读附加要求。已更新。
【解决方案3】:

您可以缓存“从第 i 个列表开始,不包括 S 中的元素”形式的计数。通过小心地将 S 限制为仅可排除的字符(即仅出现在后面列表中的元素),您可以减少重复计算量。

这是一个示例程序:

def count_uniq_combs(sets, i, excluding, cache):
    if i == len(sets): return 1
    key = (i, excluding)
    if key in cache:
        return cache[key]
    count = 0
    for c in sets[i][0]:
        if c in excluding: continue
        newx = (excluding | set([c])) & sets[i][1]
        count += count_uniq_combs(sets, i + 1, newx, cache)
    cache[key] = count
    print key, count
    return count

def count(xs):
    sets = [[set(x)] for x in xs]
    # Pre-compute the union of all subsequent sets.
    union = set()
    for s in reversed(sets):
        s.append(union)
        union = union | s[0]
    return count_uniq_combs(sets, 0, frozenset(), dict())

print count(['a', 'abcd', 'be', 'fga'])

它打印出它实际计算的值(而不是从缓存中调用),如下所示:

(3, frozenset(['a'])) 2
(2, frozenset(['a'])) 4
(2, frozenset(['a', 'b'])) 2
(1, frozenset(['a'])) 10
(0, frozenset([])) 10

例如,在查看列表 2(“b”、“e”)时,只计算了两个计数:一个是“a”和“b”都被排除在外,一个是只排除了“a”。将此与您还计算许多其他组合(例如:“a”和“c”)的幼稚实现进行比较。

如果仍然不够快,您可以尝试使用启发式方法对列表进行排序:您希望稍后出现包含相对较少其他列表符号的列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 2020-11-27
    • 2021-04-11
    • 2018-07-19
    • 1970-01-01
    • 2011-02-20
    相关资源
    最近更新 更多