【问题标题】:Sum list values within a given range using while loop使用while循环对给定范围内的列表值求和
【发布时间】:2020-08-22 08:21:09
【问题描述】:

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

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

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

使用“

我的示例数据:

# 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    = []

将while 与> = 0 一起使用;这行得通:

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)

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

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)

我用这段代码检查了输出:

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 )

对于第一个循环,打印如下:

 # 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

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

 # while command in progress 


 # Total sum
0

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

 # ulis n org values
10

【问题讨论】:

    标签: python while-loop


    【解决方案1】:

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

    >>> ulis[0] <= 0
    False
    

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

    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)
    

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

    >>> 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]
    

    为此使用for loop 更好、更简单,您可以直接循环遍历列表中的值:

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

    我将 print() 调用移到了测试中,所以它只在我找到有效值时打印:

    >>> 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
    

    如果您只想对一系列符合特定条件的值求和,您还可以在函数调用中放入generator expression,使用sum() function:

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

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

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

    您的第一个示例有效,因为输入按降序进行排序;第一个小于 0 (-2) 的值只能后跟更多小于 0 的值。如果您的输入很大,限制迭代次数可能是一个非常聪明的主意这边走。但是,您不需要 while 循环,您可以使用 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)
    

    如果您想将此属性用于您的&lt;= 0 循环,那么您需要更改迭代列表的顺序。您可以在此处使用reversed() function 执行此操作:

    # 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)
    

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

    >>> 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]
    

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

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

    如果你有两个条件,比如值在5到-4之间,输入列表非常大但仍然排序,那么您可以考虑使用binary search 查找输入列表的开始和结束索引,然后使用range() type 生成这两点之间的索引。标准库为此提供了bisect module。

    请注意,这确实意味着必须按升序顺序对值进行排序,而不是降序。

    考虑到range() 将stop 索引视为不包含在生成的索引中,因此如果您测试value &gt;= -4 和value &lt;= 5,那么您想使用bisect.bisect_right() 来查找值都大于 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))
    

    【讨论】:

    • 它确实帮助我更好地理解了这个功能。享受
    【解决方案2】:

    这种情况永远不会成立:ulis[e] &lt;= 0
    您使用了and,因此两个条件(( ulis[e] &lt;= 0) 和( e &lt; ulis_l ))都必须为真。第一个条件永远不会成立。
    此问题与 jupyter nootbook 无关。

    【讨论】:

      猜你喜欢
      • 2021-09-10
      • 2016-08-26
      • 2018-11-29
      • 2016-10-15
      • 2013-02-25
      • 2018-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多