• 【python cookbook】找出序列中出现次数最多的元素


     

    问题

    《Python Cookbook》中有这么一个问题,给定一个序列,找出该序列出现次数最多的元素。
    例如:

    words = [
       'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
       'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
       'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
       'my', 'eyes', "you're", 'under'
    ]

    统计出words中出现次数最多的元素?

    初步探讨

    1、collections模块的Counter类
    首先想到的是collections模块的Counter类,具体用法看这里!具体用法看这里!具体用法看这里!https://docs.python.org/3.6/l...,重要的事情强调三遍。

    from collections import Counter
    
    words = [
       'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
       'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
       'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
       'my', 'eyes', "you're", 'under'
    ]
    
    counter_words = Counter(words)
    print(counter_words)
    most_counter = counter_words.most_common(1)
    print(most_counter)

    关于most_common([n]):

    2、根据dict键值唯一性和sorted()函数

    import operator
    
    words = [
        'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
        'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
        'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
        'my', 'eyes', "you're", 'under'
    ]
    
    dict_num = {}
    for item in words:
        if item not in dict_num.keys():
            dict_num[item] = words.count(item)
            
    # print(dict_num)
    
    most_counter = sorted(dict_num.items(),key=lambda x: x[1],reverse=True)[0]  
    print(most_counter)    

    sorted函数:
    传送门:https://docs.python.org/3.6/l...

    iterable:可迭代类型;
    key:用列表元素的某个属性或函数进行作为关键字,有默认值,迭代集合中的一项;
    reverse:排序规则. reverse = True 降序 或者 reverse = False 升序,有默认值。
    返回值:是一个经过排序的可迭代类型,与iterable一样。

    这里,我们使用匿名函数key=lambda x: x[1]
    等同于:

    def key(x):
        return x[1]

    这里,我们利用每个元素出现的次数进行降序排序,得到的结果的第一项就是出现元素最多的项。

    更进一步

    这里给出的序列很简单,元素的数目很少,但是有时候,我们的列表中可能存在上百万上千万个元素,那么在这种情况下,不同的解决方案是不是效率就会有很大差别了呢?
    为了验证这个问题,我们来生成一个随机数列表,元素个数为一百万个。
    这里使用numpy Package,使用前,我们需要安装该包,numpy包下载地址:https://pypi.python.org/pypi/...。这里我们环境是centos7,选择numpy-1.14.2.zip (md5, pgp)进行下载安装,解压后python setup.py install

    def generate_data(num=1000000):
        return np.random.randint(num / 10, size=num)

    np.random.randint(low[, high, size]) 返回随机的整数,位于半开区间 [low, high)
    具体用法参考https://pypi.python.org/pypi

    OK,数据生成了,让我们来测试一下两个方法所消耗的时间,统计时间,我们用time函数就可以。

    #!/usr/bin/python
    # coding=utf-8
    #
    # File: most_elements.py
    # Author: ralap
    # Data: 2018-4-5
    # Description: find most elements in list
    #
    
    from collections import Counter
    import operator
    import numpy as np
    import random
    import time
    
    
    def generate_data(num=1000000):
        return np.random.randint(num / 10, size=num)
    
    
    def collect(test_list):
        counter_words = Counter(test_list)
        print(counter_words)
        most_counter = counter_words.most_common(1)
        print(most_counter)
    
    
    def list_to_dict(test_list):
        dict_num = {}
        for item in test_list:
            if item not in dict_num.keys():
                dict_num[item] = test_list.count(item)
    
        most_counter = sorted(dict_num.items(), key=lambda x: x[1], reverse=True)[0]
        print(most_counter)
    
    if __name__ == "__main__":
        list_value = list(generate_data())
    
        t1 = time.time()
        collect(list_value)
        t2 = time.time()
        print("collect took: %sms" % (t2 - t1))
    
        t1 = t2
        list_to_dict(list_value)
        t2 = time.time()
        print("list_to_dict took: %sms" % (t2 - t1))

    以下结果是我在自己本地电脑运行结果,主要是对比两个方法相对消耗时间。

    当数据比较大时,消耗时间差异竟然如此之大!下一步会进一步研究Counter的实现方式,看看究竟是什么魔法让他性能如此好。

    参考资料

    https://blog.csdn.net/xie_0723/article/details/51692806

  • 相关阅读:
    Docker私有仓库
    Docker入门
    HBase表的数据导出和导入
    HBase shell的使用记录
    Redis集群模式(Cluster)部署
    Oracle数据库sqlldr工具的使用
    oracle使用impdp和expdp导入导出数据
    Linux自动同步时间的方法
    Linux配置ssh免密码登陆
    Linux中逻辑卷(LV)的创建、增大和减小
  • 原文地址:https://www.cnblogs.com/ralap7/p/8931333.html
Copyright © 2020-2023  润新知