【问题标题】:Any better way to calculate product of multiple lists?有没有更好的方法来计算多个列表的乘积?
【发布时间】:2016-08-25 09:33:32
【问题描述】:

我需要根据 n 个输入列表获取所有可能的组合并对它们做一些事情。

当前代码示例:

import itertools

# example inputs
list_small = [1, 2, 3]
list_medium = [444, 666, 242]
list_huge = [1680, 7559, 5573, 43658, 530, 11772, 284, 50078, 783, 37809, 6740, 37765, 74492, 50078, 783, 37809, 6740, 37765, 74492]

# out of the input list, I need to generate all numbers from 0 to the current list element
# e.g. if I have 6, I need to get [0, 1, 2, 3, 4, 5, 6]
# if I get a list [1, 2, 3], the output will be [[0, 1], [0, 1, 2], [0, 1, 2, 3]]
# I achieved this by doing it with xrange: [x for x in xrange(0, current_list_element + 1)]
# after that, I need to generate all possible combinations using the generated lists
# I managed to do this by using itertools.product()

# print this to get all possible combinations
# print list(itertools.product(*[[x for x in xrange(0, current_list_element + 1)] for current_list_element in list_medium]))

cumulative_sum = 0
for current_combination in itertools.product(*[[x for x in xrange(0, current_list_element + 1)] for current_list_element in list_medium]):
    # now I need to do some calculations to the current combination
    # e.g. get sum of all combinations, this is just an example
    cumulative_sum += sum(current_combination)

    # another example
    # get XOR sum of current combination, more at https://en.wikipedia.org/wiki/Exclusive_or
    print reduce(operator.xor, current_combination, 0)

# runs fast for list_small, then takes some time for list_medium and then takes ages for list_huge
print cumulative_sum

这适用于较小的列表,但对于较大的列表需要无穷大/或引发运行时错误。有没有更好的方法来做到这一点?获得所有组合的更好方法?还是我以某种错误的方式使用 xrange?

我在 Python 2.7 和 Pypy 2 上试过这个。

编辑: 感谢@famagusta,我摆脱了xrange,但问题仍然存在

import itertools

# example inputs
list_small = [1, 2, 3]
list_medium = [444, 666, 242]
list_huge = [1680, 7559, 5573, 43658, 530, 11772, 284, 50078, 783, 37809, 6740, 37765, 74492, 50078, 783, 37809, 6740, 37765, 74492]

max_element = max(get_input_stones)
combo_list = range(0, max_element + 1)

cumulative_sum = 0
for current_combination in itertools.product(*combo_list):
    # now I need to do some calculations to the current combination
    # e.g. get sum of all combinations, this is just an example
    cumulative_sum += sum(current_combination)

    # another example
    # get XOR sum of current combination, more at https://en.wikipedia.org/wiki/Exclusive_or
    print reduce(operator.xor, current_combination, 0)

# runs fast for list_small, then takes some time for list_medium and then takes ages for list_huge
print cumulative_sum

【问题讨论】:

  • 如果您的解决方案已经有效,它似乎更适合代码审查而不是 SO。只是好奇为什么您需要0,因为它的乘积将始终为 0,并且不会对您的累积总和有任何输入?
  • 如果我理解正确,list_huge 您正在查看 4326103124078513425142526919770571037551206383570394447976698504265728000000 组合。任何需要这么多步骤的算法都注定要失败......
  • @Anzel 这只是一个例子,我添加了一个新的 XOR 和,我需要所有组合
  • @Armin Rigo,是的,必须有一些解决方法
  • @ivan_bilan:如果我们不知道您在每次迭代中计算的内容,我们就无法开始考虑解决方法。如果你想要一个无论你在计算什么都可以工作的解决方案,那么我只能回答“它永远不会工作,迭代太多了”。

标签: python python-2.7 itertools pypy xrange


【解决方案1】:

生成这样的嵌套列表可能会给您带来内存限制的麻烦。您可以只使用从列表中最大数生成的一个超级列表,而不是重复生成子列表。只需将索引存储在较小元素会停止的位置即可。

例如,[1, 6, 10] - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 6, 10]

第二个列表告诉您在第一个列表中的何处停止以提取感兴趣的子列表进行计算

这应该会为您节省一些空间。

list_small = [1, 2, 3]
list_medium = [444, 666, 242]
list_huge = [1680, 7559, 5573, 43658, 530, 11772, 284, 50078, 783, 37809, 6740, 37765, 74492, 50078, 783, 37809, 6740, 37765, 74492]

max_element = max(list_huge)   # being lazy here - write a max function
combo_list = range(0, max_element + 1)  # xrange does not support slicing

cumulative_sum = 0
for element in list_huge:
    cumulative_sum += sum(combo_list[:element])

print(cumulative_sum)

【讨论】:

  • "#在这里偷懒——写一个max函数"max怎么样? :-)
  • 哈哈!!是的!!奇怪,我的编辑没有显示。必须调查:P
  • 谢谢,使用 sum 只是一个示例,我添加了另一个示例,您的方法不起作用,因为您不会生成所有组合
  • 好的,我已经添加了您的解决方案来生成列表,而不是使用 xrange。算法还是很慢,我认为itertools.product是这里的问题
  • itertools.product(A, B) 的工作方式是它生成嵌套的 for 循环 for (x, y) in A for y in B 这样做会导致非常深嵌套。无法预见通用方法,您能否准确告诉我们进一步优化所需的计算?
猜你喜欢
  • 2017-11-29
  • 1970-01-01
  • 1970-01-01
  • 2022-09-25
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多