【问题标题】:Generating all the combinations of two lists and output them one by one in python生成两个列表的所有组合并在python中一一输出
【发布时间】:2016-11-29 03:26:22
【问题描述】:

我有两个列表

[1, 3, 4] [7, 8]

我想从像17,18,37,38,47,48,137,138,147,148......178,378....这样的最小组合开始生成两个列表的所有组合 现在对于每个组合,我必须测试它是否存在于其他地方,如果我发现该组合存在,那么我将停止组合生成。例如,如果我看到 17 存在,那么我将不会生成其他组合。再次,如果我发现48 存在,那么我将不会生成后面的组合。

【问题讨论】:

  • 我们不会为你做作业。
  • 如果您在作业问题上需要帮助(我猜是这个问题),请确保包括您到目前为止所做的事情并寻求建议,而不是解决方案。我会推荐阅读这个:meta.stackexchange.com/questions/10811/… 或这个:meta.stackoverflow.com/questions/253792/…
  • 这不是家庭作业。这是我正在做的一个项目的一部分。我需要从两个列表中一一生成所有组合。我只是问有没有什么有效的方法可以做到这一点,因为我正在做的方法效率不高......
  • @tanay 那么公平。你能发布你到目前为止的代码吗?
  • 另外,在您的示例中,您提供了两个已排序的列表。可以假设前两个列表被预先排序吗?

标签: algorithm list python-2.7 combinations


【解决方案1】:

这是一个非常丑陋的算法,但它对我有用。它也不是非常昂贵(当然,期望使用 itertools.combinations(a, i)... 生成所有组合):

import itertools

def all_combs(a):
    to_return = []
    temp = []
    for i in a:
        temp.append(i)
    to_return.append(temp)
    for i in range(2, len(a) + 1):
        temp = []
        for j in itertools.combinations(a, i):
            s = ""
            for k in j:
                s = s + str(k)
            temp.append(int(s)) #Get all values from the list permutation
        to_return.append(temp)
    print(to_return)
    return to_return

def all_perm(a, b):
    a_combs = all_combs(a)
    b_combs = all_combs(b)
    to_return = []
    for i in a_combs:
        for j in b_combs:
            for k in i:
                for l in j:
                    to_return.append(10**len(str(l)) * k + l)
    to_return.sort()
    for i in to_return:
        yield i

编辑:修复了未正确读取多位数值的错误 编辑:使函数充当生成器 编辑:修复了一个涉及数字的错误(通过添加排序...)

编辑:这是一个非常优秀的实现,它更接近于生成器样式。它仍然不完美,但在一般情况下应该可以提供良好的加速:

import itertools

def add_to_dict(dict, length, num):
    if not length in dict:
        dict[length] = []
    dict[length].append(num)

def sum_to_val(val):
    to_return = []
    for i in range(1, val):
        to_return.append([i, val-i])
    return to_return

def all_combs(a):
    to_return = {}
    for i in a:
        add_to_dict(to_return, len(str(i)), i)
    for i in range(2, len(a) + 1):
        for j in itertools.combinations(a, i):
            s = ""
            for k in j:
                s = s + str(k)
            add_to_dict(to_return, len(s), int(s)) #Get all values from the list permutation
    return to_return

def all_perm(a, b):
    a_combs = all_combs(a)
    b_combs = all_combs(b)
    for val in range(max(a_combs.keys())+max(b_combs.keys())+1):
        to_return = []
        sums = sum_to_val(val)
        for i in sums:
            if not(i[0] in a_combs and i[1] in b_combs):
                continue
            for j in a_combs[i[0]]:
                for k in b_combs[i[1]]:
                    to_return.append(10**len(str(k)) * j + k)
        to_return.sort()
        for i in to_return:
            yield i

【讨论】:

  • @tanay 你可能已经找到了这个,但是这个代码有一个错误。我添加了一个 sort() 来修复它,但这对于大型列表可能会很慢。我会找到更好的解决方案。
  • 嗯,经过测试,将所有值放入 to_return 并对其进行排序所需的时间是非常不可接受的。如果这对您来说是个问题,请告诉我,我可以重写算法来避免这种情况。
  • 抱歉回复晚了。我实际上修改了一些算法。我不想预先生成两个列表的所有组合,因为如果我得到组合的匹配项,那么我将停止循环。因此,我只为一个列表进行预制作,然后通过另一个列表并根据需要生成组合。当我得到一个匹配组合时,我就停在那里..
  • 是的,这也有效。我猜它会比我更新的算法慢,但如果它对您的目的足够快,那么这很重要。
  • 为什么你认为它会更慢......我想向你解释更多......假设我有两个列表 usr=[1,3,4] 和 obj=[7 ,8]。现在首先我创建列表 usr 的所有组合......所以我得到 1,3,4,13,14,34,134。现在对于组合的每个值,我正在动态创建 obj 列表的组合,并尝试查看合并的组合(来自 usr 和 obj)是否存在于某处。如果它存在,那么我就完成了,这样我就不必预先填充 obj 组合。
猜你喜欢
  • 1970-01-01
  • 2015-10-15
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多