Поиск списка объектов в Python
Предположим, что я создаю простой класс для работы аналогично структуре C-стиля, чтобы просто хранить элементы данных. Я пытаюсь выяснить, как искать список объектов для объектов с атрибутом, равным определенному значению. Ниже приведен тривиальный пример, иллюстрирующий то, что я пытаюсь сделать.
Например:
class Data:
pass
myList = []
for i in range(20):
data = Data()
data.n = i
data.n_squared = i * i
myList.append(data)
Как бы я искал список myList, чтобы определить, содержит ли он элемент с n == 5?
Я работаю в Google и просматриваю документы Python, и я думаю, что мог бы сделать это со списком, но я не уверен. Я могу добавить, что мне приходится использовать Python 2.4.3, так что любые новые функции gee-whiz 2.6 или 3.x недоступны мне.
Ответы
Ответ 1
Вы можете получить список всех соответствующих элементов со списком:
[x for x in myList if x.n == 30] # list of all elements with .n==30
Если вы просто хотите определить, содержит ли список любой элемент, который соответствует и делает это (относительно) эффективно, вы можете сделать
def contains(list, filter):
for x in list:
if filter(x):
return True
return False
if contains(myList, lambda x: x.n == 3) # True if any element has .n==3
# do stuff
Ответ 2
Простой, элегантный и мощный:
Выражение генератора в сочетании со встроенным... (python 2.5 +)
any(x for x in mylist if x.n == 10)
Использует встроенный Python any()
, который определяется следующим образом:
любой (итерируемый) ->
Вернуть True, если любой элемент итерабельного является истинным. Эквивалентно:
def any(iterable):
for element in iterable:
if element:
return True
return False
Ответ 3
Просто для полноты, не забывайте про Simplyest Thing, которая могла бы работать:
for i in list:
if i.n == 5:
# do something with it
print "YAY! Found one!"
Ответ 4
filter(lambda x: x.n == 5, myList)
Ответ 5
[x for x in myList if x.n == 30] # list of all matches
any(x.n == 30 for x in myList) # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30] # indices of all matches
def first(iterable, default=None):
for item in iterable:
return item
return default
first(x for x in myList if x.n == 30) # the first match, if any
Ответ 6
Вы можете использовать in
для поиска элемента в коллекции и для понимания списка, чтобы извлечь интересующее вас поле. Это (работает для списков, наборов, кортежей и всего, что определяет __contains__
или __getitem__
).
if 5 in [data.n for data in myList]:
print "Found it"
См. также:
Ответ 7
Рассмотрим использование словаря:
myDict = {}
for i in range(20):
myDict[i] = i * i
print(5 in myDict)
Ответ 8
Вы должны добавить метод __eq__
и __hash__
к вашему классу Data
, он может проверить, являются ли атрибуты __dict__
равными (одинаковые свойства), а затем, если их значения равны.
Если вы это сделали, вы можете использовать
test = Data()
test.n = 5
found = test in myList
Ключевое слово in
проверяет, находится ли test
в myList
.
Если вы хотите только свойство a n
в Data
, вы можете использовать:
class Data(object):
__slots__ = ['n']
def __init__(self, n):
self.n = n
def __eq__(self, other):
if not isinstance(other, Data):
return False
if self.n != other.n:
return False
return True
def __hash__(self):
return self.n
myList = [ Data(1), Data(2), Data(3) ]
Data(2) in myList #==> True
Data(5) in myList #==> False