【问题标题】:Smarter way to build this list of all possible numbers构建所有可能数字列表的更智能方法
【发布时间】:2017-06-20 08:56:27
【问题描述】:

我必须建立一个 3x2 值组合列表,其中所有可能的值都在 0.0 和 1.0 之间,按给定的步长(现在是 1/3)。

输出应该是[ [[v1, v2], [v3, v4], [v5, v6]], ... ],其中每个 v 都是介于 0.0 和 1.0 之间的值,例如:

[ [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.33]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.66]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 1.0]],
[[0.0, 0.0], [0.0, 0.0], [0.33, 0.0]],
[[0.0, 0.0], [0.0, 0.0], [0.33, 0.33]],
...,
[[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]] ]

到目前为止我有:

step = 1.0/3.0
lexica = []
for num1 in numpy.arange(0.0, 1.0, step):
    for num2 in numpy.arange(0.0, 1.0, step):
        for num3 in numpy.arange(0.0, 1.0, step):
            for num4 in numpy.arange(0.0, 1.0, step):
                for num5 in numpy.arange(0.0, 1.0, step):
                    for num6 in numpy.arange(0.0, 1.0, step):
                        lexica.append([[num1, num2],[num3, num4],[num5, num6]])

这并没有得到 1.0 的最高值,并且知道 Python 必须有更好的编写方式。

【问题讨论】:

    标签: python list numpy


    【解决方案1】:

    您可以使用numpy.mgrid 并对其进行操作以提供您想要的输出

    np.mgrid[0:1:step, 0:1:step, 0:1:step, 0:1:step, 0:1:step, 0:1:step].T.reshape(-1, 3, 2)
    

    编辑:

    一种更可扩展的方法来修复端点:

    def myMesh(nSteps, shape = (3, 2)):
        c = np.prod(shape)
        x = np.linspace(0, 1, nSteps + 1)
        return np.array(np.meshgrid(*(x,)*c)).T.reshape((-1, ) + shape)
    
    myMesh(3)
    
    array([[[ 0.        ,  0.        ],
            [ 0.        ,  0.        ],
            [ 0.        ,  0.        ]],
    
           [[ 0.        ,  0.33333333],
            [ 0.        ,  0.        ],
            [ 0.        ,  0.        ]],
    
           [[ 0.        ,  0.66666667],
            [ 0.        ,  0.        ],
            [ 0.        ,  0.        ]],
    
           ..., 
           [[ 1.        ,  0.33333333],
            [ 1.        ,  1.        ],
            [ 1.        ,  1.        ]],
    
           [[ 1.        ,  0.66666667],
            [ 1.        ,  1.        ],
            [ 1.        ,  1.        ]],
    
           [[ 1.        ,  1.        ],
            [ 1.        ,  1.        ],
            [ 1.        ,  1.        ]]])
    

    【讨论】:

    • 非常好!虽然你必须提高上限; 0.99... 应该包含在结果中。
    • 它包含在我的机器上。你的step 值是多少?
    • 很好,但如果尺寸可变(NxM 输出而不是 3x2),则解决方案不可扩展。
    • UPS。在那种情况下很抱歉。使用step = 1/3。但可能step = 0.33 是 OP 想要的(?)。
    • 是的,我只是在使用step=.33,如果你使用step=1./3.,它就不能包含在内(因为.999.....==1)。
    【解决方案2】:

    如果没有 numpy,你可以这样做:

    from itertools import product
    
    ret = []
    for a, b, c, d, e, f in product(range(4), repeat=6):
        ret.append([[a/3, b/3], [c/3, d/3], [e/3, f/3]])
    

    甚至作为列表理解:

    ret = [[[a/3, b/3], [c/3, d/3], [e/3, f/3]] 
           for a, b, c, d, e, f in product(range(4), repeat=6)]
    

    【讨论】:

    • 此解决方案有效,但无法针对可变维度进行扩展。同样使用numpy.linspace 更适合生成初始数组。
    【解决方案3】:

    您可以使用itertools.combinations_with_replacement 来完成该任务:

    >>> from itertools import combinations_with_replacement as cwr
    >>> cwr(cwr(numpy.linspace(0, 1, 4), 2), 3)
    

    cwr(numpy.linspace(0, 1, 4), 2)numpy.linspace(0, 1, 4)(即0, 1/3, 2/3, 1)的元素中创建长度为2 的所有可能组合。外部调用 cwr(..., 3) 然后从之前的 2 元组创建所有可能的长度为 3 的元组,从而产生 3x2 元素。

    【讨论】:

    • 这行得通,但是有没有一种动态的方法来获取“列表”的元素数量?或者我必须根据步长在其他地方制定这个。这是稍后在任务中需要的
    • @Horseshaq 我不确定我是否理解正确。 numpy.linspace(0, 1, 4) 是你的起点,你也可以改成numpy.arange(0, 1, 0.33) 如果你喜欢。结果是一个迭代器,您可以将其转换为列表:list(cwr(...))。请注意,此方法尚不包含排列(但是,如果需要,可以添加它们)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    相关资源
    最近更新 更多