Есть ли способ выполнить поиск объекта в списке по параметру в python?

#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