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

b5lpy0ml  于 2023-06-04  发布在  Python
关注(0)|答案(7)|浏览(299)

我想做这样的事情。

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

我该怎么办?我不知道我是否应该把元组编辑它或计算出元组索引?
有什么帮助吗?

i7uq4tfw

i7uq4tfw1#

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

# 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时,它的计数被初始化为零,然后在计数上加1。
但是一个充满计数的字典也是一种常见的模式,所以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()]
pgccezyw

pgccezyw2#

使用默认值可以工作,但也可以:

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

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

qyuhtwio

qyuhtwio3#

使用defaultdict:

from collections import defaultdict

urls = defaultdict(int)

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

qv7cva1a4#

这对我来说总是很好:

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

2exbekwf5#

除了第一次之外,每次看到一个单词时,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

hfsqlsce

hfsqlsce6#

完全按照你的方式去做?你可以用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吗?例如,如果你把它排序为一个dict,通过url字符串索引,它会更干净:

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)

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

  • 看看如何使用一个dict为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

使用defaultdict的立场可以变得非常优雅:

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

wribegjk7#

它也可以用标准字典来完成。

urls = {}

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

相关问题