在Python中搜索对象列表

时间:2010-11-12 04:32:08

标签: python

我有一个具有日期属性的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)

5 个答案:

答案 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例程,而不是在一次点击中对整个列表进行排序,似乎也可以提供性能提升。没有完全按照发布的测试,但应该足以让你到那里。