Break and return inside multiple for-loops with co

2019-08-21 04:27发布

问题:

I have created a long code, consist of multiple lists inside for-loops. There are nothing wrong with calculation.It does obtain results as it is expected to. The code and construction of lists work fine. The problem is when it runs, I have defined a break when a certain condition is matched. But it does not break at first run, continues and run through all values within range function of first loop. I want to achieve to return a true value, when the condition is matched, and stops and will not keep growing according to range values in first loop.

I would explain how the code would work!

The code: First part is consistent and are inputs

import math
import numpy as np


Ned = -500
fcd = 20
fyd = 435
E = 2e5
h = 200
cb = 35
ct = 35
ca = 35
b= 150
y = 12
d = h - cb
ds = ct
a = 25
yb = 8
ecu = 0.0035
rebarnumber = math.floor((b-(2*cb+2*yb+y))/a)
PI_Y2_4 = int(math.pi/4*(y)**2)
disc = []
dis = []
Asi = []
Asci = []
Esc = []
Esci = []
Sc = []
Sci =[]
#############################
# Calculation starts here
#############################

for n in range(0,10):         # <------- First for-loop
    cbb = cb + yb + y/2
    ctt = ct + yb + y/2

    if  0 < n <= rebarnumber:
        Asi.append(PI_Y2_4)
        dis.append( h - cbb)
        Asci.append(PI_Y2_4)
        disc.append( ctt )
    if  rebarnumber < n <= (2 * rebarnumber):
        Asi.append(PI_Y2_4)
        dis.append( h - cbb - ca)
        Asci.append(PI_Y2_4)
        disc.append(cbb + ca)
    if (2*rebarnumber) < n <= (3 * rebarnumber):
        Asi.append(PI_Y2_4)
        dis.append( h - cbb - 2*ca)
        Asci.append(PI_Y2_4)
        disc.append(cbb + 2*ca)
    if (3*rebarnumber) < n <= (4 * rebarnumber):
        Asi.append(PI_Y2_4)
        dis.append( h - cbb - 3*ca)
        Asci.append(PI_Y2_4)
        disc.append(cbb + 3*ca) 
    if (4*rebarnumber) < n <= (5 * rebarnumber):
        Asi.append(PI_Y2_4)
        dis.append( h - cbb - 4*ca)
        Asci.append(PI_Y2_4)
        disc.append(cbb + 4*ca)  
    if (5*rebarnumber) < n <= (6 * rebarnumber):
        Asi.append(PI_Y2_4)
        dis.append( h - cbb - 5*ca)
        Asci.append(PI_Y2_4)
        disc.append(cbb + 5*ca)
    if (6*rebarnumber) < n <= (7 * rebarnumber):
        Asi.append(PI_Y2_4)
        dis.append( h - cbb - 6*ca)
        Asci.append(PI_Y2_4)
        disc.append(cbb + 6*ca)
    if (7*rebarnumber) < n <= (8 * rebarnumber):
        Asi.append(PI_Y2_4)
        dis.append( h - cbb - 7*ca)
        Asci.append(PI_Y2_4)
        disc.append(cbb + 7*ca)

    for i in range(0,len(dis)):
        Esc.insert(i, dis[i])
        Esci.insert(i, disc[i])
        Sc.insert(i, dis[i])
        Sci.insert(i, disc[i])

        for x in np.linspace(1,h,10000):    # <-------- Second for-loop
            for k, _ in enumerate(Esc):
                try:    
                    if x < dis[k]:
                        Esc[k]=( ecu/x*(dis[k]-x) )
                    else:
                        Esc[k]=(- ecu/x*(x-dis[k] ) )

                    if x < disc[k]:
                        Esci[k]=( -ecu/x*(x-disc[k]) )
                    else:
                        Esci[k]=(- ecu/x*(x-disc[k]) )
                except (ZeroDivisionError, RuntimeWarning):
                    Esc[k]=( 0 )
                    Esci[k]=( 0 )       

            for k, _ in enumerate(Sc):       # <-------- Third for-loop
                ss = Esc[k]*E
                if ss <= -fyd:
                    Sc[k]= -fyd
                elif ss >= -fyd and ss < 0:
                    Sc[k]=ss
                else:
                    Sc[k]=min(ss,fyd)

            for k, _ in enumerate(Sci):
                sci = Esci[k]*E
                if sci <= -fyd:
                    Sci[k]= -fyd
                elif sci >= -fyd and sci < 0:
                    Sci[k]=sci
                else:
                    Sci[k]=min(sci,fyd)

            FS = 0
            FSC = 0
            for a, _ in enumerate(Sc):
                FS += Sc[a]*Asi[a]
                FSC+=Sci[a]*Asci[a]

            MS = 0        
            MSC = 0
            for m, _ in enumerate(Sc):
                MS += Sc[a]*Asi[a]*(dis[m]-h/2)
                MSC+= Sci[a]*Asci[a]*(h/2-disc[m])

            Nrd = 0
            Mrd = 0
            Nrd = int((-0.8*x*b*fcd+FSC+FS)/1000)
            Mrd = (0.8*x*b*fcd*(h/2-0.4*x)+MS-MSC)/1000000

            if 0 <= (float(Nrd) - Ned) <= 1:
                print(Nrd, x, Asi)
                break
        break    

How does it work?

First for-loop creates a list with index 0 i.e. [value1], second for-loop makes a x value increment ( range), third for-loops creates lists depend on first created list [value1]. then Nrd value determines based on increment of x values. if condition 0 <= (float(Nrd) - Ned) <= 1: is met, then the calculation would stop and return Nrd value. if not matched, it goes back and take index 1 from first for-loop, [value1, value2] is created, again reach to Nrd if condition is met, would break otherwise continues until it is matched.

My problem is when the code runs, I get those outputs.

 Nrd       x             Asi
---------------------------------------------------
-499 181.84938493849384 [113]
-499 162.36533653365336 [113, 113]
-499 147.3990399039904 [113, 113, 113]
-499 137.48784878487848 [113, 113, 113, 113]
-499 130.72117211721172 [113, 113, 113, 113, 113]
-499 126.10391039103911 [113, 113, 113, 113, 113, 113]
-499 122.7006700670067 [113, 113, 113, 113, 113, 113, 113]
-499 120.01390139013901 [113, 113, 113, 113, 113, 113, 113, 113]
-499 119.71537153715371 [113, 113, 113, 113, 113, 113, 113, 113, 113]

Above outputs are all true mutiple solutions. But I want to stop ( break) by first match, instead of giving all solutions.

I have used return True, but it is not really working here, when it complains of being out of function.

Second issue here is second for-loop for x in np.linspace(1,h,10000): I really want to run it with many decimals to get a best result, but it slows down and takes long time to calculate. Is there a way to speed up?

Perhaps defining above codelines into functions would work more efficient.

回答1:

The easiest and most straight-forward solution is to move all of your code inside a function

 def calculate_results(...args...): # Bad name, use a more suitable one
     ...
     for n in range(0, 10): # <------- First for-loop
         ...
         for x in np.linspace(1,h,10000):    # <-------- Second for-loop
         ...
         if 0 <= (float(Nrd) - Ned) <= 1:
            return Nrd, x, Asi

and then call the function afterwards

Nrd, x, Asi = calculate_results(...)
print(Nrd, x, Asi)

Use a function name that really describes the essence of what the functions is doing and do only that single thing within the function. Then the return statement makes it clear that this task is now done.