最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Updating the output of a function that takes a changing list as an input - Stack Overflow

programmeradmin1浏览0评论

I have a function called max_list that returns the largest number in a randomly generated list (I know there is an inbuilt function, this is just for practice)

import random
L = []
rang = 100 #number size limit
r = 10 #size of list

for i in range(r):
    L.append(random.randint(0, rang))

def max_list(L):
    max_in_list = L[0]
    for j in range(len(L)):
        if max_in_list == rang:         #if max_in_list is the highest it can be it must be the maximum
            return max_in_list
        elif L[j] > max_in_list:      #if tere is a value greater than max_in_list it becomes the new max_in_list
            max_in_list = L[j]
            if j+1 == r:
                return max_in_list
        elif j+1 == r:      #if it reaches the end of the list it must be the largest
            return max_in_list

My problem comes when trying to remove the largest element in the list one by one (the idea is to also append it to a new list) so for example in the list ls = [1, 2, 3] it should first remove the 3, then the 2 and so on

for k in range(len(L)):
    L.remove(max_list(L))

The thing is, it seems to be that the list does not update and max_list(L) remains fixed so on the second iteration it will append None (since it was removed in the first iteration) and result in an error: L.remove(max_list(L)) ValueError: list.remove(x): x not in list

With the example I gave before (ls = [1, 2, 3]), it would remove the 3 but on the second iteration it will try to remove the 3 instead of 2 (which would be the new max) resulting in an error

When using the inbuilt max() function it seems to work, so I think there is something wrong with the function.

I have a function called max_list that returns the largest number in a randomly generated list (I know there is an inbuilt function, this is just for practice)

import random
L = []
rang = 100 #number size limit
r = 10 #size of list

for i in range(r):
    L.append(random.randint(0, rang))

def max_list(L):
    max_in_list = L[0]
    for j in range(len(L)):
        if max_in_list == rang:         #if max_in_list is the highest it can be it must be the maximum
            return max_in_list
        elif L[j] > max_in_list:      #if tere is a value greater than max_in_list it becomes the new max_in_list
            max_in_list = L[j]
            if j+1 == r:
                return max_in_list
        elif j+1 == r:      #if it reaches the end of the list it must be the largest
            return max_in_list

My problem comes when trying to remove the largest element in the list one by one (the idea is to also append it to a new list) so for example in the list ls = [1, 2, 3] it should first remove the 3, then the 2 and so on

for k in range(len(L)):
    L.remove(max_list(L))

The thing is, it seems to be that the list does not update and max_list(L) remains fixed so on the second iteration it will append None (since it was removed in the first iteration) and result in an error: L.remove(max_list(L)) ValueError: list.remove(x): x not in list

With the example I gave before (ls = [1, 2, 3]), it would remove the 3 but on the second iteration it will try to remove the 3 instead of 2 (which would be the new max) resulting in an error

When using the inbuilt max() function it seems to work, so I think there is something wrong with the function.

Share Improve this question asked Jan 29 at 9:59 SkubaSkuba 31 silver badge2 bronze badges 3
  • The problem is that r is not anymore the size of the list when you have removed an item. So your loop will not exit with a return, and after the loop completes you have no return. – trincot Commented Jan 29 at 10:07
  • In your loop, none of the conditions will be true, and the loop will terminate. Since there's nothing else to do in the function, it will just return with a default return value of None. Specifically, if max_in_list != rang and L[j] <= max_in_list and j+1 != r - it's easy to see in what situation that would be true - as user @trincot indicated, r will no longer be the size of the list. Instead of checking if the index has reached the size of the list yet, why not just break from the loop when you're done, and always return max_in_list? – Grismar Commented Jan 29 at 10:13
  • Note also that you should not modify the list while iterating over it. – Jeyekomon Commented Jan 29 at 11:33
Add a comment  | 

4 Answers 4

Reset to default 1

The problem is that your function does not return anything explicitly (i.e. it returns None) when the if conditions are never true, which can happen when your list is shorter than r. And as you remove items, the second call of this function will indeed get a list that is shorter than r...

The very quick fix is to append a return max_in_list at the end of your function body.

But consider these remarks:

  • Instead of comparing with r, just let the loop complete (as it is the last iteration anyway). So drop those two if statements that test for j+1 == r.

  • Instead of iterating over range(len(L)), you can iterate over L, which means (together with the previous remark) you don't need to work with indices: you get the values in the list.

  • The work done to test max_in_list == rang may not be worth the effort, as the probability of hitting that value is rather small.

  • Your code assumes that the list is not empty. If you call it with an empty list you'll get an error. Maybe consider checking for the list to be empty and determine what you want to return in that case.

Rather than looping on the original list length just loop until the list is empty.

In other words change:

for k in range(len(L)):

to:

while L:

The way you're determining the maximum value in the list is unnecessarily convoluted.

The entire program could be:

from random import randint

rang = 100  # number size limit
r = 10  # size of list

L = [randint(0, rang) for _ in range(r)]


def max_list(data: list[int]) -> int:
    assert data
    m = data[0]
    for x in data[1:]:
        if x > m:
            m = x
    return m


while L:
    print(L)
    L.remove(max_list(L))

The program below does the trick. The max_list function now iterates over the values of the list keeping track of the maximum.

import random
L = []
rang = 100 #number size limit
r = 10 #size of list

for i in range(r):
    L.append(random.randint(0, rang))

def max_list(L):
    max_in_list = L[0]
    for val in L:
        if max_in_list < val:#if max_in_list is the highest it can be it m
            max_in_list = val
    return max_in_list
        
print(max(L))
print(max_list(L))
print(L)
L.remove(max_list(L))
print(L)
for k in range(len(L)):
    L.remove(max_list(L))
    print(L)
  1. Your approach had unnecessary checks (like if max_in_list == rang) that didn't help with finding the maximum value and made the code harder to understand.

  2. Looping with for in a list that changes over the code is not a good practice.

import random

L = []
rang = 100  
r = 10 

for i in range(r):
    L.append(random.randint(0, rang))

print("Original List:", L)

def max_list(L):
    max_in_list = L[0]
    for j in range(len(L)):
        if L[j] > max_in_list:
            max_in_list = L[j]
    return max_in_list

while L:
    largest = max_list(L)
    L.remove(largest)
    print(f"Remaining List: {L}")
发布评论

评论列表(0)

  1. 暂无评论