Python:字典的列表,如果存在增加一个字典值,如果不添加一个新的字典

我想要做那样的事情。

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

我能怎么做 ? 我不知道我是否应该拿这个元组进行编辑或者找出元组的指针?

任何帮助?

这是组织事情的一个非常奇怪的方式。 如果您存储在字典中,这很容易:

 # 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你可以通过调用这个类来创build一个Counter实例,传递任何可迭代的; 它build立一个字典,其中的键是来自可迭代的值,并且这些值是关键字出现在迭代中的次数。 上面的例子变成:

 from collections import Counter # available in Python 2.7 and newer urls_d = Counter(list_of_urls) 

如果你真的需要按照你所展示的方式来做,最简单和最快捷的方法就是使用这三个例子中的任何一个,然后构build一个你需要的例子。

 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()] 

使用默认的作品,但也是如此:

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

使用.get ,如果它不存在,你可以得到一个默认返回。 默认情况下它是None,但在我发送给你的情况下,它将是0。

使用defaultdict :

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

这总是适合我…

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

要做到这一点你的方式? 你可以使用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存储为列表吗? 例如,如果您将其作为字典进行sorting,则会使用urlstring进行索引,这样会更清晰:

 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列表testing一个单一的url 。 这种方法会更快。
  • 使用dict( )而不是大括号使您的代码更短
  • 使用list_of_urlsurlsurl作为variables名使代码很难parsing。 最好find更清楚的东西,比如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 

这可以得到非常优雅的defaultdict立场:

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

除了第一次,每次看到一个单词if语句的testing失败。 如果你数了大量的话,很多可能会出现多次。 在一个值初始化只发生一次的情况下,这个值的增加会多次出现,使用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