快速遍历列表并创建单个字符串的最佳方法是什么?

2 投票
3 回答
2540 浏览
提问于 2025-04-16 07:54

比如说:

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 个回答

1

在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后把它放到另一个地方。这就像是把书从一个书架搬到另一个书架一样。

有些时候,我们会遇到一些问题,比如数据的格式不对,或者我们想要的数据没有找到。这就像是你在找一本书,但书架上没有那本书,或者书的封面和你记得的不一样。

为了避免这些问题,我们可以使用一些工具或者方法来帮助我们更好地处理数据。这些工具就像是搬书的手推车,可以让我们更轻松地完成任务。

总之,处理数据的时候,保持耐心,仔细检查每一步,就能顺利完成任务。

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)
6

这里有一些速度比较,用来检查你们提到的这两种方法。

首先,我们创建一个包含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%(还要考虑到它只是函数中使用的第二个表达式)。

8

第一个例子很简单:

', '.join(item['title'] for item in list)

第二个例子稍微复杂一点,但基本上是一样的:

','.join('<a href="/u/%(title_url)s">%(title)s</a>' % item for item in list)

这两个例子都使用了生成器表达式,它们和列表推导式很像,只是不用额外创建一个列表。

撰写回答