Python: dictList,如果存在,则增加一个 dictvalue,如果不附加一个新的 dict

我也想这么做。

list_of_urls = ['http://www.google.fr/', 'http://www.google.fr/',
'http://www.google.cn/', 'http://www.google.com/',
'http://www.google.fr/', 'http://www.google.fr/',
'http://www.google.fr/', 'http://www.google.com/',
'http://www.google.fr/', 'http://www.google.com/',
'http://www.google.cn/']


urls = [{'url': 'http://www.google.fr/', 'nbr': 1}]


for url in list_of_urls:
if url in [f['url'] for f in urls]:
urls[??]['nbr'] += 1
else:
urls.append({'url': url, 'nbr': 1})

我该怎么办?我不知道是否应该使用元组来编辑它或者计算出元组索引?

有人帮忙吗?

192202 次浏览

完全按照你的方式来做? 你可以使用 for... else 结构

for url in list_of_urls:
for url_dict in urls:
if url_dict['url'] == url:
url_dict['nbr'] += 1
break
else:
urls.append(dict(url=url, nbr=1))

但是它非常不优雅。您真的必须将访问的 url 存储为一个 LIST 吗? 例如,如果你把它排序成一个用 url 字符串编制索引的 dict,它会干净得多:

urls = {'http://www.google.fr/': dict(url='http://www.google.fr/', nbr=1)}


for url in list_of_urls:
if url in urls:
urls[url]['nbr'] += 1
else:
urls[url] = dict(url=url, nbr=1)

在第二个例子中有几点需要注意:

  • 看看如何使用一个字典为 urls消除了需要通过整个 urls列表时,一个单一的 url测试。这种方法会更快。
  • 使用 dict( )代替大括号可以使代码更短
  • 使用 list_of_urlsurlsurl作为变量名使得代码很难解析。最好找一些更清晰的东西,比如 urls_to_visiturls_already_visitedcurrent_url。我知道,更长。但现在更清楚了。

当然,我假设 dict(url='http://www.google.fr', nbr=1)是对您自己的数据结构的简化,因为否则,urls可能只是:

urls = {'http://www.google.fr':1}


for url in list_of_urls:
if url in urls:
urls[url] += 1
else:
urls[url] = 1

违约判决的姿势可以让它变得非常优雅:

urls = collections.defaultdict(int)
for url in list_of_urls:
urls[url] += 1

这是一种非常奇怪的组织事物的方式。如果你把它存储在字典里,这很简单:

# This example should work in any version of Python.
# urls_d will contain URL keys, with counts as values, like: {'http://www.google.fr/' : 1 }
urls_d = {}
for url in list_of_urls:
if not url in urls_d:
urls_d[url] = 1
else:
urls_d[url] += 1

这段用于更新计数字典的代码是 Python 中常见的“模式”。它是如此普遍,以至于有一个特殊的数据结构,defaultdict,创建它只是为了使这更加容易:

from collections import defaultdict  # available in Python 2.5 and newer


urls_d = defaultdict(int)
for url in list_of_urls:
urls_d[url] += 1

如果您使用密钥访问 defaultdict,而该密钥不在 defaultdict中,则该密钥将自动添加默认值。defaultdict接受您传入的可调用性,并调用它以获取默认值。在本例中,我们传递了类 int; 当 Python 调用 int()时,它返回一个零值。因此,第一次引用 URL 时,它的计数被初始化为零,然后向计数中添加一个。

但是一个充满计数的字典也是一种常见的模式,所以 Python 提供了一个随时可用的类: containers.Counter你只需要通过调用这个类来创建一个 Counter实例,传入任何迭代; 它构建一个字典,其中的键是来自迭代的值,值是迭代中键出现的次数的计数。上面的例子就变成了:

from collections import Counter  # available in Python 2.7 and newer


urls_d = Counter(list_of_urls)

如果您真的需要按照演示的方式来做,最简单和最快速的方法是使用这三个示例中的任何一个,然后构建您需要的示例。

from collections import defaultdict  # available in Python 2.5 and newer


urls_d = defaultdict(int)
for url in list_of_urls:
urls_d[url] += 1


urls = [{"url": key, "nbr": value} for key, value in urls_d.items()]

如果你正在使用 Python 2.7或更新的版本,你可以用一行程序来完成:

from collections import Counter


urls = [{"url": key, "nbr": value} for key, value in Counter(list_of_urls).items()]

使用 违约判决:

from collections import defaultdict


urls = defaultdict(int)


for url in list_of_urls:
urls[url] += 1

使用默认值是可行的,但也是可行的:

urls[url] = urls.get(url, 0) + 1

使用 .get,如果不存在默认返回值,则可以获得该返回值。默认情况下,它是 Nothing,但是在我发送给您的情况下,它是0。

这对我来说总是很管用:

for url in list_of_urls:
urls.setdefault(url, 0)
urls[url] += 1

除了第一次,每次看到一个单词时 if 语句的测试都会失败。如果您计算的单词数量很大,那么很多单词可能会出现多次。如果一个值的初始化只发生一次,并且该值的增加会发生很多次,那么使用 try 语句会更便宜:

urls_d = {}
for url in list_of_urls:
try:
urls_d[url] += 1
except KeyError:
urls_d[url] = 1

你可以了解更多: https://wiki.python.org/moin/PythonSpeed/PerformanceTips