使用 while 循环对给定范围内的列表值求和 [英] Sum list values within a given range using while loop

查看:46
本文介绍了使用 while 循环对给定范围内的列表值求和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对列表的值求和,但前提是列表值在特定范围内(例如 介于 5 和 -4 之间,或 <= 0)

  • 使用 while 循环来解决这个问题.
  • 不要使用额外的列表.

如果我在语句中使用小于来检查列表值,代码将不起作用.

使用<"时我哪里出错了?

我的示例数据:

# 列表ulis = [ 5 , 4 , 4 , 3 , 1 , -2 , -3 , -5 , -7 , -7 ]#e 0 1 2 3 4 5 6 7 8 9# 列表长度ulis_l = len (ulis)# 计算总数总计_1 = 0#索引nr列表ε = 0# 用于总计的数字列表lprt = []

使用 while>= 0;这有效:

print ( " # while command in progress " )而 ( ulis[e] >= 0) 和 ( e 

相同的代码,将 >= 0 更改为 <= 0 不起作用,我不明白发生了什么:

print ( " # while command in progress " )而 ( ulis[e] <= 0) 和 ( e 

我用这个代码来检查输出:

print ( " " )打印 ( " " )打印(#总和")打印 (total_1)打印 ( " " )print ( " # values used form org list ulis for Total sum ")打印 (lprt)打印 ( " " )打印(#ulis n 组织值")打印 ( ulis_l )

对于第一个循环,打印:

 # while 命令进行中59131617# 总和17# 用于总和的值来自组织列表 ulis[5, 4, 4, 3, 1]# ulis n 组织值10

但是对于第二个循环,我看到:

 # while 命令进行中# 总和0# 用于总和的值来自组织列表 ulis[]# ulis n 组织值10

解决方案

不要使用while,它在第一个错误结果处停止.您的循环不起作用,因为您测试的第一个值大于零,因此不满足循环的条件:

<预><代码>>>>ulis[0] <= 0错误的

当某个值不应添加到总数中时,您不希望停止循环.您想忽略该值并继续下一个值.如果您必须使用 while 循环,则在 if 语句中使用单独的测试:

while e 

那是因为您想访问ulis 列表中的每个值,以测试它们是否需要包含在内.这是上述循环的演示:

<预><代码>>>>ulis = [5, 4, 4, 3, 1, -2, -3, -5, -7, -7]>>>ulis_l = len(ulis)>>>e = total_1 = 0>>>lprt = []>>>当 e

使用 更好,也更容易for 循环 为此,您可以直接遍历列表中的值:

for ulis 中的值:如果值 <= 0:lprt.append(值)total_1 += 值打印(total_1)

我将 print() 调用移动到测试中,因此它仅在找到有效值时才打印:

<预><代码>>>>lprt, total_1 = [], 0>>>对于 ulis 的价值:...如果值 <= 0:... lprt.append(value)... total_1 += 值...打印(total_1)...-2-5-10-17-24

如果您只想对符合特定条件的一系列值求和,您还可以输入 生成器表达式 在函数调用中,使用 sum() 函数:

total_1 = sum(如果值 <= 0,则为 ulis 中的值的值)

对于相同的结果,这是一个更紧凑的表达式:

<预><代码>>>>sum(如果值 <= 0,则为 ulis 中的值的值)-24

您的第一个示例有效,因为输入按降序排序;小于 0 (-2) 的第一个值只能后跟更多小于 0 的值.如果您的输入很大,限制迭代次数可能是一个非常聪明的主意这边走.但是,您不需要 while 循环,您只需使用 break 语句:

# 第一次循环,值大于 0对于 ulis 的价值:如果值 <= 0:# 输入按降序排序,# 所以所有剩余的值 _will_ 更小.# 为了节省时间,我们可以提前结束循环.休息# 只对大于 0 的值求和total_1 += 值lprt.append(值)

如果您想在 <= 0 循环中使用此属性,则需要更改迭代列表的顺序.您可以使用 reversed() 函数 这里:

#第二次循环,求和小于等于0的值对于反向值(ulis):如果值>0:# 输入按升序迭代,# 所以所有剩余的值 _will_ 大于零.# 为了节省时间,我们可以提前结束循环.休息# 只对小于或等于 0 的值求和total_1 += 值lprt.append(值)

当你在后面的版本中添加一个print()时,你可以看到这些值是按照相反的顺序相加的:

<预><代码>>>>lprt, total_1 = [], 0>>>对于反向值(ulis):...如果值>0:... 休息... total_1 += 值... lprt.append(value)...打印(total_1)...-7-14-19-22-24>>>文件[-7, -7, -5, -3, -2]

如果您需要 lprt 以正确的前向顺序排列,您可以通过取负索引的完整切片再次反转排序:

lprt = lprt[::-1] # 反转 lprt 列表

如果您有两个条件,例如值在 5 到 -4 之间,并且输入列表非常大但仍已排序,那么您可以考虑使用 二进制搜索 来查找输入列表的开始和结束索引,然后使用 range() 类型生成这两个点之间的索引.标准库为此提供了 bisect 模块.

请注意,这确实意味着值必须按升序排序,而不是降序.

考虑到 range()stop 索引视为不包含在生成的索引中,因此如果您测试 value >=-4value <= 5,那么你想使用 bisect.bisect_right() 找到第一个索引,其中的值都大于5:

导入平分#升序!ulis = ulis[::-1]start_index = bisect.bisect_left(ulis, -4) # values >= -4stop_index = bisect.bisect_right(ulis, 5) # value <= 5total_1 = sum(ulis[index] for index in range(start_index,stop_index))

I'm trying to sum the values of a list, but only if list values are within a specific range (for example between 5 and -4, or <= 0)

  • Use a while loop to solve this.
  • Don't use additional lists.

The code doesn't work if I use is smaller than within the statement to check list values.

Where am I going wrong while using "<"?

My example data:

# list
ulis = [ 5 , 4 , 4 , 3 , 1 , -2 , -3 , -5 , -7 , -7 ]
 #e      0   1   2   3   4    5    6    7    8    9

# list length
ulis_l  = len (ulis)

# to count total
total_1 = 0

# index nr list
e       = 0

# list of numbers used for total 
lprt    = []

Using while with > = 0; this works:

print ( " # while command in progress " )
while ( ulis[e] >= 0) and ( e < ulis_l ):   
    total_1 = total_1 + ulis [e]
    lprt.append (ulis [e])
    e = e + 1
    print (total_1)

The same code, with >= 0 changed to <= 0 doesn't work, and I don't understand what is happening:

print ( " # while command in progress " )
while ( ulis[e] <= 0) and ( e < ulis_l ):
    total_1 = total_1 + ulis [e]
    lprt.append (ulis [e])
    e = e + 1
    print (total_1)

I used this code to check the output:

print ( " " )
print ( " " )
print ( " # Total sum " )
print (total_1)
print ( " " )
print ( " # values used form org list ulis for Total sum " )
print (lprt)
print ( " " )
print ( " # ulis n org values " )
print ( ulis_l )

For the first loop, this is printed:

 # while command in progress 
5
9
13
16
17


 # Total sum
17

 # values used form org list ulis for Total sum
[5, 4, 4, 3, 1]

 # ulis n org values
10

but for the second loop I see:

 # while command in progress 


 # Total sum
0

 # values used form org list ulis for Total sum
[]

 # ulis n org values
10

解决方案

Don't use while, it stops at the first false result. Your loop doesn't work because the first value you test is greater than zero, and so the condition for the loop is not met:

>>> ulis[0] <= 0
False

You don't want to stop the loop when a value should not be added to the total. You want to ignore that value and continue to the next value. If you must use a while loop, then use a separate test in an if statement:

while e < ulis_l:
    if ulis[e] <= 0:
        # You can use += here instead of total_1 = total_1 + ...
        total_1 += ulis[e]
        lprt.append(ulis[e])
    e = e + 1
    print(total_1)

That's because you want to visit every value in the ulis list to test if they need to be included. Here is a demo of the above loop:

>>> ulis = [5, 4, 4, 3, 1, -2, -3, -5, -7, -7]
>>> ulis_l = len(ulis)
>>> e = total_1 = 0
>>> lprt = []
>>> while e < ulis_l:
...     if ulis[e] <= 0:
...         # You can use += here instead of total_1 = total_1 + ...
...         total_1 += ulis[e]
...         lprt.append(ulis[e])
...     e = e + 1
...     print(total_1)
...
0
0
0
0
0
-2
-5
-10
-17
-24
>>> total_1
-24
>>> lprt
[-2, -3, -5, -7, -7]

It is better, and easier, to use a for loop for this, you can loop directly over the values in a list:

for value in ulis:
    if value <= 0:
        lprt.append(value)
        total_1 += value
        print(total_1)

I moved the print() call into the test, so it only prints when a valid value i found:

>>> lprt, total_1 = [], 0
>>> for value in ulis:
...     if value <= 0:
...         lprt.append(value)
...         total_1 += value
...         print(total_1)
...
-2
-5
-10
-17
-24

If all you want to do is sum a series of values that match specific criteria, you can also put a generator expression inside a function call, using the sum() function:

total_1 = sum(value for value in ulis if value <= 0)

This is a more compact expression for the same result:

>>> sum(value for value in ulis if value <= 0)
-24

Your first example worked because the input is sorted in descending order; the first value that's smaller than 0 (-2) can only be followed by more values that are lower than 0. If your input is large, it can be quite a smart idea to limit the number of iterations this way. You don't need a while loop for this however, you can just use the break statement:

# first loop, values greater than 0
for value in ulis:
    if value <= 0:
        # input is sorted in descending order,
        # so all remaining values _will_ be smaller.
        # To save time, we can end the loop early.
        break

    # only sums values greater than 0
    total_1 += value
    lprt.append(value)

If you want to make use of this property for your <= 0 loop, then you need to change the order in which you iterate the list. You can do this with the reversed() function here:

# second loop, summing values smaller than or equal to 0 
for value in reversed(ulis):
    if value > 0:
        # input is iterated over in ascending order,
        # so all remaining values _will_ be greater than zero.
        # To save time, we can end the loop early.
        break

    # only sums values smaller than or equal to 0
    total_1 += value
    lprt.append(value)

When you add a print() to the latter version, you can see that the values are added up in reverse order:

>>> lprt, total_1 = [], 0
>>> for value in reversed(ulis):
...     if value > 0:
...         break
...     total_1 += value
...     lprt.append(value)
...     print(total_1)
...
-7
-14
-19
-22
-24
>>> lprt
[-7, -7, -5, -3, -2]

If you need to have lprt in the correct, forward order, you can reverse the ordering again by taking the full slice with negative index:

lprt = lprt[::-1]   # reverse the lprt list

If you have two criteria, like the value is between 5 and -4, and the input list is very large but still sorted, then you could consider using binary search to find the start and end indices of your input list, then use the range() type to generate the indices between those two points. The standard library provides the bisect module for this.

Note that this does mean the values have to be sorted in ascending order, not descending.

Take into account that range() treats the stop index as not included in the indices that are produced, so if you test for value >= -4 and value <= 5, then you want to use bisect.bisect_right() to find the first index where the values would all be greater than 5:

import bisect

# ascending order! ulis = ulis[::-1] 

start_index = bisect.bisect_left(ulis, -4)  # values >= -4
stop_index = bisect.bisect_right(ulis, 5)  # value <= 5

total_1 = sum(ulis[index] for index in range(start_index, stop_index))

这篇关于使用 while 循环对给定范围内的列表值求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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