WhiteHeadbanger
WhiteHeadbanger

Reputation: 97

Next() skips the actual and next item in list, when it should only skip the actual item

I'm writing a program that, giving a list of integers, identify the minimum value and then remove the minimum with the minor index of the list.

Ex: list = [3, 6, 15, 2, 4, 2] should return [3, 6, 15, 4, 2] Notice the first 2 removed because of the minor index on the list.

This is my entire code:

def remove_smallest(numbers):
    mylist = []
    if not numbers:
        return mylist 
    minimo = min(numbers)
    if numbers.count(minimo) > 1:
        numbers = numbers[::-1] #My solution to the minor index is to reverse the list and loop. Then reverse again.

        #mylist = [item for item in numbers if item != minimo and item not in mylist]  #I tried to use a list comprehension, with awful results.

        it = iter(numbers)
        for item in it:
            if item == minimo and item in mylist:
                next(it, None)
                continue
            mylist.append(item)

    print(mylist[::-1])

remove_smallest([2, 4, 5, 1, 2, 1])

First two items will get appended to "mylist" (1, 2). Then, because 1 is on mylist, it will skip it and then continue. So far so good, however when it should select the 5, it does not, instead goes straight to the 4 and then 2, resulting in an array that looks like this at the end of the program: [2, 4, 2, 1] when it should return [2, 4, 5, 2, 1]

Thanks

Upvotes: 1

Views: 67

Answers (4)

Dalvenjia
Dalvenjia

Reputation: 2033

this function will remove the first occurrence of the smallest number in a list and return that number, the list is modified in-place so no need to return it:

def pop_smallest(lst):
    smallest = lst.index(min(lst))
    return lst.pop(smallest)

l = [2, 4, 5, 1, 2, 1]
pop_smallest(l)
>>> 1

l
>>> [2, 4, 5, 2, 1]

but if you don't want to modify the original list then you need to copy the list and return the new list

def pop_smallest(lst):
    new_lst = lst.copy()
    smallest = new_lst.index(min(lst))
    new_lst.pop(smallest)
    return new_lst

l = [2, 4, 5, 1, 2, 1]
new_l = pop_smallest(l)

l
>>> [2, 4, 5, 1, 2, 1]
new_l
>>> [2, 4, 5, 2, 1]

Upvotes: 1

Austin
Austin

Reputation: 26057

I will devise a new approach, as I find yours is too much code:

def remove_smallest(lst):
    mini = min(lst)
    indx = next((i for i, x in enumerate(lst) if x == mini), -1)
    del lst[indx]
    return lst

which safely removes first occurance of the minimum element in the list.

Usage:

>>> remove_smallest([2, 4, 5, 1, 2, 1])
[2, 4, 5, 2, 1]

Upvotes: 1

Deepstop
Deepstop

Reputation: 3827

A simple statement will remove the smallest value. l.index(min(l)) finds the index of the smallest value.

>>> l = [2,4,5,1,2,1]
>>> del l[l.index(min(l))]
>>> l
[2, 4, 5, 2, 1]

Upvotes: 2

Jmonsky
Jmonsky

Reputation: 1519

Removing the next statement has the code work in the expected way. The for loop is already calling next on the iterator so no need to manually.

def remove_smallest(numbers):
    mylist = []
    if not numbers:
        return mylist 
    minimo = min(numbers)
    if numbers.count(minimo) > 1:
        numbers = numbers[::-1] #My solution to the minor index is to reverse the list and loop. Then reverse again.

        it = iter(numbers)
        for item in it:
            if item == minimo and item in mylist:
                continue
            mylist.append(item)

    print(mylist[::-1])

remove_smallest([2, 4, 5, 1, 2, 1])

Results in:

[2, 4, 5, 2, 1]

Upvotes: 2

Related Questions