快速遍历列表并创建单个字符串的最佳方法是什么?
比如说:
list = [{"title_url": "joe_white", "id": 1, "title": "Joe White"},
{"title_url": "peter_black", "id": 2, "title": "Peter Black"}]
我该怎么高效地遍历这个,来创建:
Joe White, Peter Black
<a href="/u/joe_white">Joe White</a>,<a href="/u/peter_black">Peter Black</a>
谢谢你。
3 个回答
在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后把它放到另一个地方。这就像是把书从一个书架搬到另一个书架一样。
有些时候,我们会遇到一些问题,比如数据的格式不对,或者我们想要的数据没有找到。这就像是你在找一本书,但书架上没有那本书,或者书的封面和你记得的不一样。
为了避免这些问题,我们可以使用一些工具或者方法来帮助我们更好地处理数据。这些工具就像是搬书的手推车,可以让我们更轻松地完成任务。
总之,处理数据的时候,保持耐心,仔细检查每一步,就能顺利完成任务。
class node():
titles = []
urls = []
def add_name(self, a_title):
self.titles.append(a_title)
def add_url(self, a_title_url, a_title):
self.urls.append('<a href="/u/%s">%s</a>' % (a_title_url, a_title))
node = node()
for entry in list:
node.add_name(entry["title"])
node.add_url(entry["title_url"],entry["title"])
print ','.join(node.titles)
print ','.join(node.urls)
这里有一些速度比较,用来检查你们提到的这两种方法。
首先,我们创建一个包含100000个条目的列表;这可能有点无聊,而且由于字符串较短,可能不是一个真实的样本,但我现在不太担心这个。
>>> items = [{"title_url": "abc", "id": i, "title": "def"} for i in xrange(100000)]
首先是Michael Mrozek的回答:
>>> def michael():
... ', '.join(item['title'] for item in items)
... ','.join('<a href="/u/%(title_url)s">%(title)s</a>' % item for item in items)
...
简单明了。接下来是systempuntoout的回答(注意到此时我只是比较迭代的性能,所以我把%s和元组格式化换成了%()的字典格式化;我稍后会计时另一种方法):
>>> def systempuntoout():
... titles = []
... urls = []
... for item in items:
... titles.append(item['title'])
... urls.append('<a href="/u/%(title_url)s">%(title)s</a>' % item)
... ', '.join(titles)
... ','.join(urls)
...
很好。现在来计时:
>>> import timeit
>>> timeit.timeit(michael, number=100)
9.6959049701690674
>>> timeit.timeit(systempuntoout, number=100)
11.306489944458008
总结一下:不用担心遍历列表两次,结合生成器表达式,这比使用list.append的开销要小;在处理100000个条目时,Michael的解决方案快了大约15%。
其次,关于你应该使用'%(...)s' % dict()
还是'%s' % tuple()
。把Michael的回答当作两者中更快更简单的,这里是michael2
:
>>> def michael2():
... ', '.join(item['title'] for item in items)
... ','.join('<a href="/u/%s">%s</a>' % (item['title_url'], item['title']) for item in items)
...
>>> timeit.timeit(michael2, number=100)
7.8054699897766113
因此我们得出一个明确的结论:使用元组进行字符串格式化比使用字典快,快了将近25%。所以如果性能是个问题,而你又在处理大量数据,建议使用这个方法michael2
。
如果你想看看一些真的让人害怕的东西,可以看看systempuntoout的原始回答,保持类不变:
>>> def systempuntoout0():
... class node():
... titles = []
... urls = []
... def add_name(self, a_title):
... self.titles.append(a_title)
... def add_link(self, a_title_url, a_title):
... self.urls.append('<a href="/u/%s">%s</a>' % (a_title_url, a_title))
... node = node()
... for entry in items:
... node.add_name(entry["title"])
... node.add_link(entry["title_url"], entry["title"])
... ', '.join(node.titles)
... ','.join(node.urls)
...
>>> timeit.timeit(systempuntoout0, number=100)
15.253098011016846
速度几乎是michael2
的两倍慢。
最后补充一下,来对比一下在Python 2.6中引入的str.format
,被称为“字符串格式化的未来”(虽然我还是不明白为什么,我还是喜欢我的%
,谢谢;特别是因为它更快)。
>>> def michael_format():
... ', '.join(item['title'] for item in items)
... ','.join('<a href="/u/{title_url}">{title}</a>'.format(**item) for item in items)
...
>>> timeit.timeit(michael_format, number=100)
11.809207916259766
>>> def michael2_format():
... ', '.join(item['title'] for item in items)
... ','.join('<a href="/u/{0}">{1}</a>'.format(item['title_url'], item['title']) for item in items)
...
>>> timeit.timeit(michael2_format, number=100)
9.8876869678497314
11.81而不是9.70,9.89而不是7.81 - 它慢了20-25%(还要考虑到它只是函数中使用的第二个表达式)。
第一个例子很简单:
', '.join(item['title'] for item in list)
第二个例子稍微复杂一点,但基本上是一样的:
','.join('<a href="/u/%(title_url)s">%(title)s</a>' % item for item in list)
这两个例子都使用了生成器表达式,它们和列表推导式很像,只是不用额外创建一个列表。