0

我正在尝试在 django 中实现搜索功能,该功能根据字符串过滤记录列表,与django admin list filtering

但是在这里我们不会from the database根据从搜索表单中获得的查询字符串来过滤结果,而是我们需要filter from the list我已经有了

视图.py

def filter_contacts(request):
    contacts = ['None <steve.one@gmail.com>', 'None <ronold@gmail.com>', 
               'None <jacksparrow@gmail.com>', 'None <dude@gmail.com>' ...... up to more than 1000]
    if request.GET:
        if request.GET.has_key('q'):
            contacts = **filter the contacts from the above list that contains query string "q" and create a new list**
        else:
            contacts = contacts
    return render_to_response('social_feeds/gmail_contacts.html', {'contacts':contacts})

search_form 类似

<form class="form-search" action="{% url 'contacts' %}" method="get">
      <div class="input-append">
        <input type="text" class="span2 search-query" name="q" value="" id="searchbar">
        <button type="submit" class="btn btn-primary" value="Search">Search</button>
      </div>
</form>

当然,我们可以query string从列表中过滤looping并搜索列表中每个字符串中的字符串,如果它创建了一个新列表,

但是因为/假设我们有超过 1000 个字符串(电子邮件可能如上所述),这个过程应该very/ultimately很快,所以寻找functionality/process/method基于query paramerter类似假设非常快速过滤列表的

如果我们用 搜索表单steve,所有strings/emails包含的内容steve都应该被过滤到一个新列表中,这就是我要找的

谁能让我知道如何快速实现搜索功能?

4

1 回答 1

0

最快的方法是将电子邮件保存在数据库中,然后使用查询来获取它们。像这样的东西:

模型.py

class Contact(models.model):
    email = models.EmailField()

然后在views.py中:

if request.GET.has_key('q'):
    query = request.GET['q']
    contacts = Contact.objects.all().filter(email__contains=query)

如果做不到这一点,你想使用 pythonic 方式。可能有比简单循环更快的方法,但话说回来,循环并不像你想象的那么慢。我拿了一个 60k 的电子邮件列表(这个!),并以所谓的“慢速方法”循环遍历它,如下所示:

f = open('maillist.txt', 'rb')
lines = f.readlines()
res = []
for l in lines:
    if 'steve' in l:
        res.append(l)

计时显示完成大约需要 0.008 秒。

只是为了展示“简单”方法的速度有多快,我对实现相同结果的不同方法进行了计时:

timing = {}
res = []
import time

# normal iteration
start = time.time()
for l in lines:
    if 'steve' in l:
        res.append(l)
end = time.time()
timing['iteration'] = end-start
length = len(res)


res = []
# list comprehension
start = time.time()
[res.append(l) for l in lines if 'steve' in l]
end = time.time()
timing['list comprehension'] = end-start
assert(len(res) == length)

#
def search(s):
    res =[]
    if 'steve' in s:
        res.append(s)
    return res

# built in 'filter' method
start = time.time()
res = filter(search, lines)
end = time.time()
timing['filter'] = end-start
assert(len(res) == length)

#using itertools
import itertools
start = time.time()
res = itertools.ifilter(search, lines)
end = time.time()
timing['ifilter'] = end-start

for key, value in timing.iteritems():
    print key, value, 'seconds'

行是上述60k电子邮件列表的列表,结果如下:

iteration                  0.00799989700317 seconds
list comprehension         0.00699996948242 seconds
filter                     0.0130000114441 seconds
ifilter                    0.0 seconds

如您所见,最快的方法是使用列表推导。这是为了计算“史蒂夫”是否在电子邮件中,但如果你做一些更复杂的事情,比如“史蒂夫”在电子邮件中或“史密斯”在电子邮件中,那么结果会发生一些变化:

iteration                  0.0139999389648 seconds
list comprehension         0.010999917984 seconds
filter                     0.0169999599457 seconds
ifilter                    0.0 seconds

尽管如此,列表理解是赢家。您可能想知道为什么 ifilter 需要 0 时间,但这很简单 - ifilter 创建了一个生成器。动态加载结果可以证明对您的需求有效。

无论如何,您可以清楚地看到,所有这些版本之间的差异以毫秒为单位。我无法想象你需要比这更快的东西,但是你应该测试和计时不同的方法,如果你发现你仍然需要更多的东西,只需去 pypi 并寻找一个允许快速过滤的包。

于 2013-08-19T16:16:08.543 回答