【问题标题】:Finding the most common element in a list of lists在列表列表中查找最常见的元素
【发布时间】:2022-01-02 18:42:36
【问题描述】:

我得到一个这样的列表:

pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
         [(2, 2), (2, 1)], 
         [(1, 1), (1, 2), (2, 2), (2, 1)]]

所需的输出是:{(2,2)}

我需要找到最常见的元素。如果存在重复多次的元素,则它必须返回多个值。

我尝试使用三个列表的交集来解决它,但它打印出 {(2,1), (2,2)},而不是 {(2,2)},因为元素 (2,2) 在第一个列表中重复了两次。

我看到了一些import collections 的示例,但我不明白它们,所以我不知道如何更改代码以适合我的问题。

我还尝试了以下方法:

seen = set()
repeated = set()
for l in pairs:
    for i in set(l):
        if i in seen:
            repeated.add(i)
        if i in repeated:
            repeated.add(i)
        else:
            seen.add(i)

但仍然没有返回正确答案。

【问题讨论】:

  • 请使用tour、阅读what's on-topic hereHow to Askquestion checklist,并提供minimal reproducible example。 “为我实现此功能”与此站点无关,因为 SO 不是免费的在线编码服务。你必须诚实地尝试,然后就你的算法或技术提出一个具体问题
  • 你可以为一个元组列表创建一个字典,使用元组作为键和每个元组的计数作为值吗?
  • 显而易见的解决方案是遍历列表,计算每个元素出现的次数,并返回计数最高的元素。你试过吗?
  • 提示:来自collectionsdefaultdict 可能非常有用。

标签: python list frequency


【解决方案1】:

正如 cmets 中所暗示的,defaultdict 非常有帮助。

from collections import defaultdict

我们有“对”,但由于您希望在所有列表中出现最频繁,我们会将其展平。

pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
         [(2, 2), (2, 1)], 
         [(1, 1), (1, 2), (2, 2), (2, 1)]]

flat_pairs = [tpl for lst in pairs for tpl in lst]

现在我们将创建一个默认为零的defaultdict 来保存我们的计数,并遍历 flat_pairs 以将计数添加到字典中。

counts = defaultdict(lambda: 0)

for tpl in flat_pairs: 
    counts[tpl] += 1

或者我们可以跳过扁平化阶段:

counts = defaultdict(lambda: 0)

for lst in pairs:
    for tpl in lst: 
        counts[tpl] += 1

我们可以通过在字典的值上使用max 来找到最大计数值,然后使用列表推导式来获取具有最大计数的元组。

max_count = max(counts.values())

max_count_tuples = [tpl for tpl, count in counts.items() if count == max_count]

【讨论】:

    【解决方案2】:

    不使用collections 中的Counter 方法的替代解决方案:

    def get_freq_tuple(data):
        counts = {}
        for pairs in data:
            for pair in pairs:
                counts[pair] = counts.get(pair, 0) + 1
    
        return [pair for pair in counts if counts[pair] == max(counts.values())]
    
    if __name__ == "__main__":
        pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1),
                  (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)],
                 [(2, 2), (2, 1)],
                 [(1, 1), (1, 2), (2, 2), (2, 1)]]
        print(get_freq_tuple(pairs))
    

    输出:

    [(2, 2)]
    

    说明:

    • 计算每个元组的出现次数并将它们存储在字典中。字典的键是元组,值是出现。
    • 按元组的最大出现次数过滤字典中的元组。

    免责声明:

    • 使用collections 中的Counter 方法效率更高。

    参考资料:

    【讨论】:

      【解决方案3】:

      collections.Counter() 将起作用...您只需要弄清楚如何传递嵌套列表中的所有对,您可以通过列表理解来做到这一点。例如:

      from collections import Counter
      
      pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
               [(2, 2), (2, 1)], 
               [(1, 1), (1, 2), (2, 2), (2, 1)]]
      
      counts = Counter(pair for l in pairs for pair in l)
      counts.most_common(1)
      # [((2, 2), 4)]
      

      如果您有平局,则需要查看排名靠前的选项并挑选出具有相同计数的选项。你可以通过查看counts.most_common()获取排序列表。

      itertools.groupby 是处理此问题的常用方法。例如,如果您有平局,您可以获得所有排名靠前的条目,例如:

      from collections import Counter
      from itertools import groupby
      
      pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
               [(2, 2), (2, 1)], 
               [(1, 1), (1, 2), (2, 2), (2, 1), (3, 2)]]
      
      counts = Counter(pair for l in pairs for pair in l)
      
      count, groups = next(groupby(counts.most_common(), key=lambda t: t[1]))
      [g[0] for g in groups]
      # [(2, 2), (3, 2)]
      

      【讨论】:

        猜你喜欢
        • 2010-12-03
        • 2017-06-14
        • 2018-09-11
        • 2012-11-12
        • 1970-01-01
        相关资源
        最近更新 更多