Удаление объекта из списка?

Итак, я все еще начинающий программист, которому поручили сортировать объекты, созданные файлом csv с атрибутами lname, fname, полом, возрастом (именно в таком порядке), и сортировать их по атрибуту lname. Я добился этого, однако теперь мне нужно удалить один из объектов (я выбрал случайный для тестирования), и это то, что у меня есть до сих пор:

class FitClinic:
    def __init__(self, lname, fname, gender, age):
        self.lname = lname
        self.fname = fname
        self.gender = gender
        self.age = int(age)

    def __del__(self):
        print("Customer has been deleted")

    def get_lname(self):
        return self.lname

    def get_fname(self):
        return self.fname

    def get_gender(self):
        return self.gender

    def get_age(self):
        return self.age

fh=open('fit_clinic_20.csv', 'r')
fh.seek(3)
listofcustomers=[]
for row in fh:
    c = row.split(",")
    listofcustomers.append(FitClinic(c[0], c[1], c[2], c[3]))

sorted_list=sorted(listofcustomers,key=lambda x: x.get_lname())

for x in sorted_list:
    if x.get_lname()==("Appleton"):
        del x
    print(x.get_lname(),x.get_fname(),x.get_gender(),x.get_age())

теперь это явно не работает, и мне нужна помощь.


person osmans    schedule 28.12.2019    source источник


Ответы (4)


del x просто удаляет временную переменную x, она не влияет на список. Вам нужно использовать del listofcustomers[pos], но сначала вам нужно найти позицию в списке.

try:
    pos = next(i for i,v in enumerate(listofcustomers) if v.get_lname() == "Appleton")
    del listofcustomers[pos]
except StopIteration:
    pass // Ignore if not found

См. Python: возвращает индекс первого элемента списка, который делает переданную функцию истинной для множества способов найти индекс элемента, который соответствует критерию.

person Barmar    schedule 28.12.2019
comment
Поскольку вы не используете возврат из pop, del listofcustomers[pos] кажется более прямым (и немного более быстрым) решением. del работает для удаления по индексу или для удаления атрибутов, а не только необработанных имен верхнего уровня. - person ShadowRanger; 28.12.2019
comment
Вероятно, это не имеет большого значения, но это кажется более простым. - person Barmar; 28.12.2019

Вы можете удалить элемент из списка с пониманием списка:

sorted_list[:] = [x for x in sorted_list if not(x.get_lname()==("Appleton"))]

Рабочий пример:

class FitClinic:
    def __init__(self, lname):
        self.lname = lname

    def __del__(self):
        print("Customer has been deleted")

    def get_lname(self):
        return self.lname

# Create example
sorted_list = [FitClinic('a'), FitClinic('b'), FitClinic('c'), FitClinic('Appleton')]
sorted_list[:] = [x for x in sorted_list if not(x.get_lname()=="Appleton")]

Теперь sorted_list есть.

a
b
c
person Leonardo Mariga    schedule 28.12.2019
comment
Могу я предложить x.get_lname() != "Appleton" вместо not(x.get_lname()=="Appleton")? - person ShadowRanger; 28.12.2019
comment
@ShadowRanger Да, вы можете использовать это, если хотите. - person Leonardo Mariga; 28.12.2019

Этот пример лучше с filter, так как он удаляет все клиники, где lname Appleton:

sorted_list = list(filter(lambda c: c.get_lname() != "Appleton", sorted_list))

Если вы хотите удалить только первый, используйте ответ Бармара.

Это то же самое, что и понимание списка, которое Python лучше оптимизирует:

sorted_list = [c for c in sorted_list if c.get_lname() != "Appleton"]
person Anonymous    schedule 28.12.2019
comment
Если вам нужен lambda для использования filter, он будет медленнее, чем эквивалентный listcomp, которому он не нужен; sorted_list = [c for c in sorted_list if c.get_lname() != "Appleton"] быстрее и лаконичнее (а также более Pythonic, если вы слушаете BDFL, который вообще ненавидит filter). - person ShadowRanger; 28.12.2019
comment
@ShadowRanger Ты прав. filter может быть понятнее, но здесь было бы лучше понимание списка. - person Anonymous; 28.12.2019

Просто попробуйте это:

for x in sorted_list:  # Loops through Customers in List
    if x.get_lname() == "Appleton":  # Check if the last name is Apple
        sorted_list.remove(x)  # Remove each from the list, Pretty self explanatory
    else:  # you only want to print if the last name is not APppleton
        print(x.get_lname(), x.get_fname(), x.get_gender(), x.get_age())

.remove удаляет объект из списка, поэтому вам не нужно отслеживать индекс цикла. Прочтите это руководство w3schools, чтобы узнать больше об операциях со списками.

person Community    schedule 28.12.2019
comment
редактирование списка во время его повторения вызывает проблемы. - person Mark Tolonen; 28.12.2019