Python 从具有最大int值的对(字符串,int)列表中查找字符串集

Python 从具有最大int值的对(字符串,int)列表中查找字符串集,python,string,set,max,Python,String,Set,Max,我有一个(str,int)对的列表 list_word=[('AND',1),('BECAUSE',1),('OF',1),('AFRIAD',1),('NEVER',1),('CATS',2),('ARE',2),('FRIENDS',1),('DOGS',2)] 这基本上就是说每个单词在一篇文章中出现了多少次 我想得到的是一组出现次数最多的单词以及出现次数最多的单词。在上面的例子中,我想 (集合(['CATS','DOGS','ARE']),2) 我能想到的解决办法是循环浏览列表。但是有什么

我有一个
(str,int)
对的列表

list_word=[('AND',1),('BECAUSE',1),('OF',1),('AFRIAD',1),('NEVER',1),('CATS',2),('ARE',2),('FRIENDS',1),('DOGS',2)]

这基本上就是说每个单词在一篇文章中出现了多少次

我想得到的是一组出现次数最多的单词以及出现次数最多的单词。在上面的例子中,我想

(集合(['CATS','DOGS','ARE']),2)


我能想到的解决办法是循环浏览列表。但是有什么优雅的方法可以做到这一点吗?

两次线性扫描,首先找到最大元素:

maxcount = max(map(itemgetter(1), mylist)) 
然后,第二次拉出您关心的值:

maxset = {word for word, count in mylist if count == maxcount}, maxcount
如果您需要获得的集合不止是最大计数,您可以使用在一次传递中按计数累积:

from collections import defaultdict

sets_by_count = defaultdict(set)

for word, count in mylist:
    sets_by_count[count].add(word)

然后,它后面可以是
allcounts=sorted(set_by_count.items(),key=itemgetter(0),reverse=True)
以获得
计数列表,从最高计数到最低计数(排序工作最少,因为它只对与唯一计数相等的项目进行排序,而不是对所有单词进行排序)。

两次线性扫描,首先找到最大元素:

maxcount = max(map(itemgetter(1), mylist)) 
然后,第二次拉出您关心的值:

maxset = {word for word, count in mylist if count == maxcount}, maxcount
如果您需要获得的集合不止是最大计数,您可以使用在一次传递中按计数累积:

from collections import defaultdict

sets_by_count = defaultdict(set)

for word, count in mylist:
    sets_by_count[count].add(word)

然后,后面可以是
allcounts=sorted(sets_by_count.items(),key=itemgetter(0),reverse=True)
获取
count的
列表,设置
对,从最高到最低计数(排序工作最少,因为它只对与唯一计数相等的项目进行排序,而不是对所有单词进行排序).

列表
转换为
目录
,键作为计数,值作为单词集。找到键的
max
值,并将其删除;s对应值

from collections import defaultdict
my_list = [('AND', 1), ('BECAUSE', 1), ('OF', 1), ('AFRIAD', 1), ('NEVER', 1), ('CATS', 2), ('ARE', 2), ('FRIENDS', 1), ('DOGS', 2)]
my_dict = defaultdict(set)
for k, v in my_list:
    my_dict[v].add(k)

max_value = max(my_dict.keys())
print (my_dict[max_value], max_value)
# prints: (set(['CATS', 'ARE', 'DOGS']), 2)

list
转换为
dict
,键作为计数,值作为单词集。找到键的
max
值,并将其删除;s对应值

from collections import defaultdict
my_list = [('AND', 1), ('BECAUSE', 1), ('OF', 1), ('AFRIAD', 1), ('NEVER', 1), ('CATS', 2), ('ARE', 2), ('FRIENDS', 1), ('DOGS', 2)]
my_dict = defaultdict(set)
for k, v in my_list:
    my_dict[v].add(k)

max_value = max(my_dict.keys())
print (my_dict[max_value], max_value)
# prints: (set(['CATS', 'ARE', 'DOGS']), 2)

虽然更多的pythonic解决方案当然更容易看到,但不幸的是,对两次扫描或构建您并不真正想要的数据结构的要求要慢得多

以下相当枯燥的解决方案比dict解决方案快约55%,比基于提供的示例数据(以及我的实现、机器、基准测试等)的基于理解的解决方案快约70%

这几乎可以肯定是一次扫描,而不是两次扫描

word_occs = [
    ('AND', 1), ('BECAUSE', 1), ('OF', 1), ('AFRIAD', 1), ('NEVER', 1),
    ('CATS', 2), ('ARE', 2), ('FRIENDS', 1), ('DOGS', 2)
]


def linear_scan(word_occs):
    max_val = 0
    max_set = None

    for word, occ in word_occs:
        if occ == max_val:
            max_set.add(word)

        elif occ > max_val:
            max_val, max_set = occ, {word}

    return max_set, max_val

平心而论,它们都非常快,在您的情况下,可读性可能更重要。

虽然更具pythonic风格的解决方案显然更容易看到,但不幸的是,需要两次扫描,或者构建您并不真正想要的数据结构的速度要慢得多

以下相当枯燥的解决方案比dict解决方案快约55%,比基于提供的示例数据(以及我的实现、机器、基准测试等)的基于理解的解决方案快约70%

这几乎可以肯定是一次扫描,而不是两次扫描

word_occs = [
    ('AND', 1), ('BECAUSE', 1), ('OF', 1), ('AFRIAD', 1), ('NEVER', 1),
    ('CATS', 2), ('ARE', 2), ('FRIENDS', 1), ('DOGS', 2)
]


def linear_scan(word_occs):
    max_val = 0
    max_set = None

    for word, occ in word_occs:
        if occ == max_val:
            max_set.add(word)

        elif occ > max_val:
            max_val, max_set = occ, {word}

    return max_set, max_val

平心而论,它们都非常快,在您的情况下,可读性可能更重要。

调用变量
list
可能是一件危险的事情。啊,感谢您指出。我写这篇文章只是为了简单明了。现在编辑调用变量
列表
可能是一件危险的事情。啊,谢谢你指出。我写这篇文章只是为了简单明了。现在编辑