#python #list #object
#python #Список #объект
Вопрос:
В моей программе есть функция, которая обновляет объект, хранящийся в списке, и другая функция, которая определяет положение объектов в этом списке. У всех объектов есть параметр «id», и мне было интересно, есть ли способ поиска объекта в этом списке исключительно с помощью параметра «id»
Это find_position()
функция:
def find_position(self, object):
for i in range(len(self._objectsList)):
if self._objectsList[i] == object:
return i
return -1
Комментарии:
1. Вам следует попробовать изменить свой код, чтобы он находил объект по идентификатору. Я не вижу здесь попытки.
2.
next((obj for obj in objects if obj.id == id_to_look_for), None)
илиnext(filter(lambda obj: obj.id == id_to_look_for, objects), None)
?3. Если вы перезапишете,
__hash__(self)
вы можете использоватьindex(obj)
.4. @Detlef нет,
index
не использует__hash__
. Он использует равенство (и, возможно, идентичность в качестве оптимизации)5. Извините, это была моя ошибка.
Ответ №1:
Предполагая, что вы можете получить доступ к атрибуту id через object.id:
def find_position_by_id(self, id):
for el in self._objectsList:
if el.id == id:
return self._objectsList.index(el)
return -1
Вы также могли бы подумать об использовании dict внутри вашего основного объекта, чтобы сохранить другие объекты. Ключами dict могут быть идентификаторы других объектов.
Ответ №2:
Поскольку вы ищете индекс первого объекта, .id
равный некоторому значению, и, похоже, хотите зафиксировать это в функции:
def find_position_by_id(objects, identifier):
return next((i for i, obj in enumerate(objects) if obj.id == identifier), -1)
Объясняется в несколько шагов:
enumerate(objects)
возвращает итерацию, которая генерирует кортежи индексов и значенийobjects
, т.е.(0, objects[0])
,(1, objects[1])
и т.д.i for i, obj in enumerate(objects)
это генератор, который принимает эти индексы и значения по одному за раз и присваивает ихi
иobj
, генерируя по ходу дела только значенияi
.i for i, obj in enumerate(objects) if obj.id == identifier
это тот же самый генератор, но он генерирует только значенияi
в паре с объектамиobj
,.id
значение которых равноidentifier
- Вводя это в
next(<iterable>, -1)
, вы получаете только первое значение из этого генератора, или-1
если в генераторе нет значений.
Итак, next((i for i, obj in enumerate(objects) if obj.id == identifier), -1)
вы получаете то, что вам нужно, и вы можете обернуть это в функцию или метод, как в вашем примере кода.
Сопоставьте с некоторыми примерами данных:
from dataclasses import dataclass
@dataclass
class Obj:
id: int
value: str
objects = [Obj(10, 'Alice'), Obj(20, 'Bob'), Obj(30, 'Charlie')]
def find_position_by_id(xs, identifier):
return next((i for i, x in enumerate(xs) if x.id == identifier), -1)
print(find_position_by_id(objects, 20))
Результат:
1