Python中while循环和列表索引的问题

3

我有一个循环的问题。我想将“公称直径”设置为“nominal_diameters”列表中的值。例如,我的“calc_diameter=130”,所以我希望“nominal_diameter=125”。到目前为止,在这段代码中,我得到了“nominal_diameter=0”的结果。

我应该在循环中做什么改变?

import math

print('Welcome in PipeDiameter program. It helps you to choose the right size of pipe for'
      ' sewerage pressure systems.')
flow=round(float(input('Please enter your sewage flow [(m^3)/s]:')),2)
speed_assumed = 1
calc_diameter=round(math.sqrt(((4*flow)/((math.pi)*speed_assumed))*1000),2)
print(str(calc_diameter)+' mm')

nominal_diameters=[90,110,125,160,180,200,225,250,315,355,400,450,500,560,630,710,800]
inner_diameters=[(90-2*5,4),(110-2*6,6),(125-2*7,4),(160-2*9,5),(180-2*10,7),(200-2*11,9),
                 (225-2*13,4),(250-2*14,8),(315-2*18,7),(355-2*21,1),(400-2*23,7),(450-2*26,7),
                 (500-2*29,7),(560-2*33,2),(630-2*37,4),(710-2*42,1),(800-2*47,4)]

nominal_diameter=0
i=0

while nominal_diameters[i]<=calc_diameter<=nominal_diameters[i+1]:
    nominal_diameter=nominal_diameters[i]
    i=i+1
print(nominal_diameter)

如果 calc_diameter=130,为什么 nominal_diameter=125?而不是160?或者如果 calc_diameter=124 呢?还有厚度列表呢? - iGian
你真的需要这个条件吗?calc_diameter<=nominal_diameters[i+1]? - Raman Mishra
1
第一个检查条件 90 <= 130 <= 110 失败,因此循环从未进入。您能解释一下您在循环中尝试做什么吗?nominal_diameter 是否应该是列表中最接近 calc_diameter 的值? - shriakhilc
如果删除第二个条件 calc_diameter<=nominal_diameters[i+1],你将得到所需的输出。 - Raman Mishra
1
@iGian,对于calc_diameter=130,nominal_diameter应该是125而不是160,因为它与进一步的计算有关。在我的示例中,speed_assumed为1,这个速度是最小的。在进一步的计算中,我将计算管道内的实际速度。为了做到这一点,我需要厚度列表内径。并且随着管道越小,速度越快,这就是为什么nominal_diameter应该比calc_diameter低的原因。你在不知情的情况下提供了帮助。谢谢! - lenncb
4个回答

1
问题在于如果第一个值不满足条件,循环就不会进入,因此您的公称直径将被评估为0。您可以按照以下方式更改代码。

while True:
        if nominal_diameters[i] <= calc_diameter <= nominal_diameters[i + 1]:
            nominal_diameter = nominal_diameters[i]
            break
        i = i + 1

这应该解决问题。

1
问题在这里:

while nominal_diameters[i] <= calc_diameter <= nominal_diameters[i+1]:

假设 calc_diameter = 300,那么该语句的含义是
while 90 <= 300 <= 110:

这将立即失败,使您得到0

您可以通过执行以下操作来解决它:

for i in range(len(nominal_diameters)-1):
    if nominal_diameters[i] <= calc_diameter <= nominal_diameters[i+1]:
        nominal_diameter = nominal_diameters[i]
        break
else:
    if calc_diameter < nominal_diameters[0]:
        nominal_diameter = nominal_diameters[0]
    else:
        nominal_diameter = nominal_diameters[-1]

1
我理解你想要根据calc_diameter找到最接近的nominal_diameters列表中的值。你可以按照以下方式进行操作(以calc_diameter=130为例):
import numpy as np

nominal_diameters=[90,110,125,160,180,200,225,250,315,355,400,450,500,560,630,710,800]
calc_diameter = 130

best_approx = np.argmin([np.abs(d-calc_diameter) for d in nominal_diameters]) # Provides the index in nominal_diameters with value closest to calc_diameter
print(nominal_diameters[best_approx]) # Outputs 125

我遇到了错误:'AttributeError: module 'numpy' has no attribute 'argmin'。你知道我做错了什么吗? - lenncb
奇怪,numpy 绝对有 argmin 函数,我测试过这段代码,而且对我来说也运行正常。 - b-fg

1

由于问题看起来像是一个选择,因此可以使用替代while循环的方法:

nominal_diameters=[90,110,125,160,180,200,225,250,315,355,400,450,500,560,630,710,800]

calc_diameter = 130
select_diam = min([(abs(d-calc_diameter), d) for d in nominal_diameters ])[1]

print(select_diam) #=> 125

对于 calc_diameter = 195,它返回 200工作原理 通过 列表推导式,将 nominal_diameters 列表映射到一个元组列表,该元组包含这样一对值:所需直径与公称直径之间的绝对差值(abs())和公称直径本身((abs(d-calc_diameter), d))。
然后从列表中选择最小的元组(min()),最后从最小值中选择第二个元素([1]),即公称直径。
以下是 calc_diameter = 130 的映射示例:
[(40, 90), (20, 110), (5, 125), (30, 160), (50, 180), (70, 200), (95, 225), (120, 250), (185, 315), (225, 355), (270, 400), (320, 450), (370, 500), (430, 560), (500, 630), (580, 710), (670, 800)]
                      ^^^^^^^^

这个并没有按照预期工作。对于 calc_diameter=195,你会得到 180 而不是 200。 - b-fg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接