我有一个具有日期属性的Item对象列表。我也有一个从数据库中抓取的日期。
我想在列表中搜索,找到大于我从数据库返回的日期的所有列表项。
我的Items对象列表中有超过一千个对象,所以我希望尽可能高效。
我假设循环遍历列表中的每个项目并检查它是否大于我从db返回的日期并不是最有效的方法。
class Item(object):
def __init__(self, title, link, description, date):
self.title = title
self.link = link
self.description = description
self.date = date
item_list = []
...
#assume I populate the list with a 1,000 Item objects
filtered_list = []
for it in item_list:
if date_from_db > it.date:
filtered_list.append(it)
答案 0 :(得分:4)
列表推导是在数据库之外执行此操作的一种非常有效的方法:
[it for it in item_list if date_from_db > it.date]
否则,您可以使用filter
内置:
filter(lambda it: it if date_from_db > it.date, item_list)
答案 1 :(得分:2)
避免遍历列表中每个项目的唯一方法是按日期对其进行排序,然后向后搜索,直到找到大于目标日期的最后一项,并将其添加到filtered_list
为你走了。
或者将列表降序排序并向前搜索,直到找到大于目标的第一个项目为止。这可以让你轻松修改你的循环:
filtered_list = []
for it in item_list:
if date_from_db > it.date:
filtered_list.append(it)
else:
break
或者,如果您希望过滤后的列表中包含多个项目,则可以更快地执行binary search查找符合条件的第一个项目,并使用列表切片将其复制到{{ 1}}:
filtered_list
这是我从上一段中的链接改编的二元搜索功能。我相信它应该有效:
first = binary_search(item_list, lambda it: cmp(date_from_db, it.date))
if first == -1:
return []
return item_list[first:]
答案 2 :(得分:1)
在回应声称此列表组合令人困惑的说法时,我将发布一种格式化它的方法。我最近一直在使用它。
filtered_list = [item # What we're collecting
for item in item_list # What we're collecting it over
if date_from_db < item.date] # the conditions
它确实可以将单个衬里变成三个衬里就像使用常规for循环一样但是在比这更差的情况下(甚至在这里)它提高了可读性和让你效率提高了。
答案 3 :(得分:0)
您可以使用过滤器:
filtered_list = filter(lambda(item): date_from_db < item.date, item_list)
或者你可以用来理解:
filtered_list = [item for item in item_list if date_from_db < item.date]
我相信人们更喜欢后者,但我喜欢前者。 Lambda只是一个内联函数 - 如果你愿意,你可以使该函数显式化。
答案 4 :(得分:-1)
对列表进行排序然后将其平分。如果您正在寻找一个特定项目,并且还将根据其属性解决查找对象的难题,则此方法也是如此。
# add __eq__ and __lt__ functions to your object so they'll sort by date
class Item(object):
"""blah blah as above"""
def __eq__(self, other):
return self.date == other.date
def __lt__(self, other):
"""Order by date ascending"""
return self.date < other.date
# sort that puppy
item_list = sorted(item_list)
# mock up an item to faux search for
item_from_db = Item(None, None, None, date_from_db)
# find the index of it's rightful place
idx = bisect.bisect(item_list, item_from_db)
# aberacadabera
return item_list[idx:]
为使用append
的{{1}}实施filtered_list
例程,而不是在一次点击中对整个列表进行排序,似乎也可以提供性能提升。没有完全按照发布的测试,但应该足以让你到那里。