避免嵌套for循环python [英] avoiding nested for loops python

查看:609
本文介绍了避免嵌套for循环python的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,它接受表达式并将变量替换为我用作输入的值的所有排列.这是我已测试并可以正常工作的代码,但是,在仔细研究了SO之后,人们说嵌套的for循环是一个坏主意,但是我不确定如何提高效率.有人可以帮忙吗?谢谢.

I have a function which takes in expressions and replaces the variables with all the permutations of the values that I am using as inputs. This is my code that I have tested and works, however after looking through SO, people have said that nested for loops are a bad idea however I am unsure as to how to make this more efficient. Could somebody help? Thanks.

def replaceVar(expression):

    eval_list = list()

    a = [1, 8, 12, 13]
    b = [1, 2, 3, 4]
    c = [5, 9, 2, 7]

    for i in expression:
        first_eval = [i.replace("a", str(j)) for j in a]
        tmp = list()
        for k in first_eval:
            snd_eval = [k.replace("b", str(l)) for l in b]
            tmp2 = list()
            for m in snd_eval:
                trd_eval = [m.replace("c", str(n)) for n in c]
                tmp2.append(trd_eval)
            tmp.append(tmp2)
        eval_list.append(tmp)
    print(eval_list)
    return eval_list

print(replaceVar(['b-16+(c-(a+11))', 'a-(c-5)+a-b-10']))

推荐答案

前言

嵌套循环本身并不是一件坏事.如果发现了更好的算法,它们只会是不好的问题(针对输入大小的效率,更好而又不好).例如,对整数列表进行排序就是这样的问题.

Foreword

Nested loops are not a bad thing per se. They are only bad, if there are used for problems, for which better algorithm have been found (better and bad in terms of efficiency regarding the input size). Sorting of a list of integers for example is such a problem.

在上面的例子中,您有三个大小均为4的列表.如果a始终位于b之前并且b始终位于c之前,则这将使4 * 4 * 4 = 64种可能的组合.因此,您至少需要进行64次迭代!

In your case above you have three lists, all of size 4. This makes 4 * 4 * 4 = 64 possible combinations of them, if a comes always before b and b before c. So you need at least 64 iterations!

在您的方法中,我们对a的每个可能值进行4次迭代,对b的每个可能值进行4次迭代,对c进行相同的迭代.因此,我们总共有4 * 4 * 4 = 64次迭代.因此,实际上您的解决方案是非常好的! 由于没有更快的方法来收听所有组合,因此您的方法也是最好的方法.

In your approach we have 4 iterations for each possible value of a, 4 iterations for each possible value of b and the same for c. So we have 4 * 4 * 4 = 64 iterations in total. So in fact your solution is quite good! As there is no faster way of listening all combinations, your way is also the best one.

关于样式,可以说您可以通过使用更好的变量名并结合一些for循环来改进代码.例如.像这样:

Regarding the style one can say that you can improve your code by better variable names and combining some of the for loops. E.g. like that:

def replaceVar(expressions):
    """
    Takes a list of expressions and returns a list of expressions with
    evaluated variables.
    """
    evaluatedExpressions = list()

    valuesOfA = [1, 8, 12, 13]
    valuesOfB = [1, 2, 3, 4]
    valuesOfC = [5, 9, 2, 7]

    for expression in expressions:
        for valueOfA in valuesOfA:
            for valueOfB in valuesOfB:
                for valueOfC in valuesOfC:
                    newExpression = expression.\
                                    replace('a', str(valueOfA)).\
                                    replace('b', str(valueOfB)).\
                                    replace('c', str(valueOfC))
                    evaluatedExpressions.append(newExpression)

    print(evaluatedExpressions)
    return evaluatedExpressions

print(replaceVar(['b-16+(c-(a+11))', 'a-(c-5)+a-b-10']))

但是请注意,迭代次数保持不变!

Notice however that the amount of iterations remain the same!

注意到 Kevin ,您也可以使用itertools生成笛卡尔积.在内部,它的作用与您在合并后的for循环中所做的相同:

As Kevin noticed, you could also use itertools to generate the cartesian product. Internally it will do the same as what you did with the combined for loops:

import itertools

def replaceVar(expressions):
    """
    Takes a list of expressions and returns a list of expressions with
    evaluated variables.
    """
    evaluatedExpressions = list()

    valuesOfA = [1, 8, 12, 13]
    valuesOfB = [1, 2, 3, 4]
    valuesOfC = [5, 9, 2, 7]

    for expression in expressions:
        for values in itertools.product(valuesOfA, valuesOfB, valuesOfC):
            valueOfA = values[0]
            valueOfB = values[1]
            valueOfC = values[2]
            newExpression = expression.\
                            replace('a', str(valueOfA)).\
                            replace('b', str(valueOfB)).\
                            replace('c', str(valueOfC))
            evaluatedExpressions.append(newExpression)

    print(evaluatedExpressions)
    return evaluatedExpressions

print(replaceVar(['b-16+(c-(a+11))', 'a-(c-5)+a-b-10']))

这篇关于避免嵌套for循环python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆