如何有效地进行大排列?

时间:2019-06-11 21:03:21

标签: python

我需要按0.05的间隔对从0到1的每个值组成的列表进行排列。

我已经尝试使用itertools的置换方法(或函数),但是该程序花了很多时间才能完成置换,甚至在运行Spyder时使它崩溃。我还需要在排列的每个实例中的每个数字加起来为1(在下面的代码片段中此示例)。我什至无法测试对代码所做的更改,因为这会使我的计算机停止工作。有什么建议吗?

weight.append(i for i in list(itertools.permutations(weights)) if sum(i)<=1.04 and sum(i)>=0.96) 

我进行了两次总和检查,因为数字的总和未精确得出1,所以我不能只尝试if sum(i)==1。确实没有将任何内容添加到列表中,我需要将结果添加到列表中,但这是一个不同的问题。

2 个答案:

答案 0 :(得分:0)

您的评论揭示了您的追求。这不是排列,而是笛卡尔积
Python 中,将其“翻译”为[Python 3.Docs]: itertools.product(*iterables, repeat=1)

code.py

#!/usr/bin/env python3

import sys
from itertools import product


def filter_values(values, min_sum=0, max_sum=100, count=3):
    for item in product(values, repeat=count):
        if min_sum <= sum(item) <= max_sum:
            yield item


def main():
    weights = [float(i) / 100 for i in range(0, 105, 5)]
    print("Weights: {:}\n".format(weights))

    filtered_weights = list(filter_values(weights, min_sum=0.96, max_sum=1.04))  # @TODO - cfati: !!! NOTA BENE: list(...) is for display purposes only! I guess its (disastrous) effects are quite familiar when it comes to large amounts of data !!!
    print("Filtering yielded {:d} elements".format(len(filtered_weights)))
    if (len(filtered_weights)):
        print("  First: {:}\n  Last: {:}".format(filtered_weights[0], filtered_weights[-1]))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()
    print("\nDone.")

输出

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q056551640]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32

Weights: [0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0]

Filtering yielded 231 elements
  First: (0.0, 0.0, 1.0)
  Last: (1.0, 0.0, 0.0)

Done.

答案 1 :(得分:0)

考虑到问题的精确度(在注释中),您可以使用简单的列表理解来获得所有这些“排列”:

combos = [ (x/20,y/20,(20-x-y)/20) for x in range(21) for y in range(21-x) ]

# 231 combinations:
#
# [(0.0, 0.0, 1.0), (0.0, 0.05, 0.95), (0.0, 0.1, 0.9), (0.0, 0.15, 0.85), ... 
#  ... (0.95, 0.0, 0.05), (0.95, 0.05, 0.0), (1.0, 0.0, 0.0)]