【问题标题】:How to reduce the no. of for loops in python code如何减少编号。 python代码中的for循环
【发布时间】:2019-08-29 19:00:15
【问题描述】:

我想生成一个 csv 文件,其中包含以下格式的行 不。列数是动态的,它可能会随着变量“n”的值而变化。所以,如果我们有 n=3 将有 3 列: 第一行在第一行的每个单元格中初始化为 1/3 值,如下所示 0.333 0.333 0.333 类似地,如果 n=6,将有 6 列,并且第一行在第一行的每个单元格中初始化为 1/6 值。 0.166667 0.166667 0.166667 0.166667 0.166667 0.166667

每行所有元素之和必须等于 1。

没有限制。的行。我们只担心元素之和应该等于1。 下表是我的代码生成的 csv 文件的前几行:

0.166667 0.166667 0.166667 0.166667 0.166667 0.166667 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0.166667 0.833333 0 0 0 0 0.333333 0.666667 0 0 0 0 0.5 0.5 0 0 0 0 0.666667 0.333333

我是编程新手,我认为我的逻辑效率不高。我正在尝试找出一种方法来减少我在下面的代码中使用的 for 循环的数量。如果 n 的值增加,则没有。如果我们按照我的逻辑,for 循环的数量也会增加。请帮帮我。

import csv
n = 6 #This variable is controlled by other factors and may change
f = [0, 1]

for i in range(1, n):
    j = float(i) / float(n)
    f.append(j)

# Generate WS
initial = float(1) / float(n)
w = []
for i in range(n):
    w.append(initial)
ws = [w]
for i in f:
    for j in f:
        for k in f:
            for l in f:
                for m in f:
                    for o in f:
                        if (i + j + k + l + m + o == 1):
                            w = [i, j, k, l, m, o]
                            ws.append(w)
with open('weight.csv', 'w') as cfile:
    cwrite = csv.writer(cfile)
    cwrite.writerows(ws)

预期的 csv:

0.166666667 0.166666667 0.166666667 0.166666667 0.166666667 0.166666667

0 0 0 0 0 1

0 0 0 0 1 0

0 0 0 0 0.166666667 0.833333333

0 0 0 0 0.333333333 0.666666667

0 0 0 0 0.5 0.5

0 0 0 0 0.666666667 0.333333333

0 0 0 0 0.833333333 0.166666667

0 0 0 1 0 0

0 0 0 0.166666667 0 0.833333333

等等..有很多行,但显示前几行。

【问题讨论】:

    标签: python-3.x csv for-loop


    【解决方案1】:

    你可以使用itertools.product:

    from itertools import product
    
    n = 6 # or whatever number >= 1
    
    for I in product(*[f] * n):
        if sum(I) == 1:
            ws.append(list(I))
    

    然后您可以通过索引I 来提取您的i, j, k, ...,因此iI[0]jI[1],...等等。

    【讨论】:

    • 变量 n 一直在变化,它不是一个常数 6。那么,有没有办法切断 i,j,kl,.... for 循环?如果 n 为 7,则应该有另一个循环,如果它是 8,则应该有 8 个循环,依此类推
    • 使用product 来生成所有可能的组合只是为了丢弃绝大多数不等于 1 的组合,这是非常浪费和低效的。仅使用蛮力方法作为最后的手段。
    • @blhsing 你说的很对,当我第一次回答这个问题时,我只考虑了嵌套 for 循环的问题,并没有真正检查里面的代码。
    • 效率差异演示(为您修复了上述错误):repl.it/repls/InnocentPrudentProjects
    • 啊,我没有重新加载页面,错过了你上次的编辑,你修复了无条件ws.append(w)的错误。
    【解决方案2】:

    您可以在 rangen 上使用 itertools.combinations_with_replacement 来生成所有索引组合,在其中将 1 / n 添加到每个有效行中,然后将 map 它添加到 collections.Counter 进行总结每个索引处的所有1 / ns,然后在rangen 上使用嵌套列表推导将总和放入相应的索引中:

    from itertools import combinations_with_replacement
    from collections import Counter
    n = 3
    [[c[i] / n for i in range(n)] for c in map(Counter, combinations_with_replacement(range(n), n))]
    

    这会返回:

    [[1.0, 0.0, 0.0],
     [0.6666666666666666, 0.3333333333333333, 0.0],
     [0.6666666666666666, 0.0, 0.3333333333333333],
     [0.3333333333333333, 0.6666666666666666, 0.0],
     [0.3333333333333333, 0.3333333333333333, 0.3333333333333333],
     [0.3333333333333333, 0.0, 0.6666666666666666],
     [0.0, 1.0, 0.0],
     [0.0, 0.6666666666666666, 0.3333333333333333],
     [0.0, 0.3333333333333333, 0.6666666666666666],
     [0.0, 0.0, 1.0]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-13
      • 2013-10-21
      • 2021-03-18
      • 2023-03-25
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      相关资源
      最近更新 更多