zoukankan      html  css  js  c++  java
  • python之collections模块(nametuple,Counter)

    前言:

    import collections
    print([name for name in dir(collections) if not name.startswith("_")])
    ['AsyncIterable', 'AsyncIterator', 'Awaitable', 'ByteString', 'Callable', 'ChainMap', 'Container', 'Coroutine', 
    'Counter', 'Generator', 'Hashable', 'ItemsView', 'Iterable', 'Iterator', 'KeysView', 'Mapping', 'MappingView', 
    'MutableMapping', 'MutableSequence', 'MutableSet', 'OrderedDict', 'Sequence', 'Set', 'Sized', 'UserDict', 'UserList', 
    'UserString', 'ValuesView', 'abc', 'defaultdict', 'deque', 'namedtuple']

     常用:

    a)Counter: 计数器,用于统计元素的数量

    b)OrderDict:有序字典

    c)defaultdict:值带有默认类型的字典

    d)namedtuple:可命名元组,通过名字来访问元组元素

    e)deque :双向队列,队列头尾都可以放,也都可以取(与单向队列对比,单向队列只能一头放,另一头取)

    1.from collections import namedtuple

    from collections import namedtuple
    
    # 定义一个namedtuple类型User,并包含name,sex和age属性。
    User = namedtuple('User', ['name', 'sex', 'age'])

    也可以不用列表使用空格间隔的str也可以
    User = namedtuple('User', 'name sex age')
    # 创建一个User对象 user = User(name='wqb', sex='male', age=24) # 也可以通过一个list来创建一个User对象,这里注意需要使用"_make"方法 user = User._make(['wqb', 'male', 24]) print(user) # User(name='wqb', sex='male', age=24) # 获取用户的属性 print(user.name) print(user.sex) print(user.age) # 修改对象属性,注意要使用"_replace"方法 user = user._replace(age=22) print(user) # User(name='wqb', sex='male', age=22) # 将User对象转换成字典,注意要使用"_asdict" print(user._asdict()) # OrderedDict([('name', 'wqb'), ('sex', 'male'), ('age', 22)])

    适用地方:

    学生信息系统:

           (名字,年龄,性别,邮箱地址)为了减少存储开支,每个学生的信息都以一个元组形式存放

           如:

           ('tom', 18,'male','tom@qq.com' )

           ('jom', 18,'mal','jom@qq.com' ) .......

           这种方式存放,如何访问呢?

    #!/usr/bin/python3
     
    student = ('tom', 18, 'male', 'tom @ qq.com' )
    print(student[0])
    if student[1] > 12:
        ...
    if student[2] == 'male':  
        ...

    出现问题,程序中存在大量的数字index,可阅读性太差,无法知道每个数字代替的含义=》

    如何解决这个问题?

    方法1:

    #!/usr/bin/python3
     
    # 给数字带上含义,和元组中一一对应
    name, age, sex, email = 0, 1, 2, 3                        
    # 高级:name, age, sex, email = range(4)
    student = ('tom', 18, 'male', 'tom @ qq.com' )
    print(student[name])
    if student[age] > 12:
         print('True')
    if student[sex] == 'male':
        print('True')

    方法2:

      通过 collections库的 nametuple模块

    rom collections import namedtuple
     
    # 生成一个Student类
    Student = namedtuple('Student', ['name', 'age', 'sex', 'email'])
     
    s = Student('tom', 18, 'male', 'tom@qq.com')
    
    print(s.name, s.age, s.sex, s.email)

     2.from collections import counter

    用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。

    创建:

    # 创建一个空的Counter类
    c0=Counter()
    
    # 从一个可iterable对象(list、tuple、dict、字符串等)创建
    cs=Counter("axcvcx")
    cl=Counter([1,2,3,4])
    cm=Counter({'a':2,'c':3,'d':5})
    
     # 从一组键值对创建
    ceq=Counter(a=2,b=3,c=6)

    Counter()
    Counter({'x': 2, 'c': 2, 'v': 1, 'a': 1})
    Counter({1: 1, 2: 1, 3: 1, 4: 1})
    Counter({'d': 5, 'c': 3, 'a': 2})
    Counter({'c': 6, 'b': 3, 'a': 2})

    用键访问计数值

    当键不存在的时候,不会报错而是返回0

    >>> c = Counter("abcdefgab")
    >>> c["a"]
    2
    >>> c["c"]
    1
    >>> c["h"]
    0

     计数器更新

    增加和减法(update,substract)==>参数可以是iterable对象也可是Counter对象==>没有返回值,修改的是本身

    c=Counter("asdfgg")
    c2=Counter("aaa")
    c.update(c2)
    print(c)
    # Counter({'a': 4, 'd': 1, 'f': 1, 'g': 2, 's': 1})
    c.update("ssss")
    print(c)
    # Counter({'s': 5, 'a': 4, 'g': 2, 'd': 1, 'f': 1})
    c=Counter("asdfgg")
    c2=Counter("aaa")
    c.subtract(c2)
    print(c)
    # Counter({'g': 2, 'f': 1, 'd': 1, 's': 1, 'a': -2})
    c.subtract("ssss")
    print(c)
    # Counter({'g': 2, 'f': 1, 'd': 1, 'a': -2, 's': -3})

    键的删除和修改

    当值为零的时候并不意味着值被删除,要删除‘键值对’用 del

    c=Counter("asdfgg")
    c.subtract("s")
    print(c)
    # Counter({'g': 2, 'f': 1, 'd': 1, 'a': 1, 's': 0})
    del c["a"]
    print(c)
    # Counter({'g': 2, 'f': 1, 'd': 1, 's': 0})

    elements()

    返回一个迭代器<class 'itertools.chain'>。元素被重复了多少次,在该迭代器中就包含多少个该元素。元素排列无确定顺序,个数小于1的元素不被包含。

    c=Counter({"a":1,"b":2,"c":-1,"d":0,"e":5})
    print(type(c.elements()),c.elements(),list(c.elements()))
    # <class 'itertools.chain'> 
    # <itertools.chain object at 0x0000020D9A71D5F8>
    # ['e', 'e', 'e', 'e', 'e', 'a', 'b', 'b']

    most_common(n)

    返回一个TopN列表。------>说明是排好顺序的(有序)。如果n没有被指定,则返回所有元素。当多个元素计数值相同时,优先返回key键Hash靠前的。

    def most_common(self, n=None):
        '''List the n most common elements and their counts from the most
        common to the least.  If n is None, then list all element counts.
        >>> Counter('abcdeabcdabcaba').most_common(3)
        [('a', 5), ('b', 4), ('c', 3)]
        '''
        # Emulate Bag.sortedByCount from Smalltalk
        if n is None:
            return sorted(self.items(), key=_itemgetter(1), reverse=True)
        return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
    c=Counter({"a":1,"b":2,"c":-1,"d":1,"e":5})
    print(c.most_common())
    # [('e', 5), ('b', 2), ('a', 1), ('d', 1), ('c', -1)]
    print(c.most_common(3))
    # [('e', 5), ('b', 2), ('a', 1)]

    浅拷贝copy

    c=Counter({"a":1,"b":2,"c":-1,"d":1,"e":5})
    c2=c.copy()
    print(c2)
    # Counter({'e': 5, 'b': 2, 'd': 1, 'a': 1, 'c': -1})
    c.update("aaa")
    print(c2)
    # Counter({'e': 5, 'b': 2, 'd': 1, 'a': 1, 'c': -1})

    算数和集合操作

    +、-、&、|操作也可以用于Counter。其中&和|操作分别返回两个Counter对象各元素的最小值和最大值。需要注意的是,得到的Counter对象将删除小于1的元素。

    c1=Counter({"a":1,"b":2,"c":-1,"d":1,"e":5})
    c2=Counter(a=2,b=3)
    #值小于0的数结果不显示
    c1+c2 #
    # Counter({'a': 3, 'b': 5, 'd': 1, 'e': 5})
    c2-c1 #
    # Counter({'a': 1, 'b': 1, 'c': 1})
    c1=Counter({"a":1,"b":2,"c":-1,"d":1,"e":5})
    c2=Counter(a=2,b=3)
    ## 交集:  保留相同key键的并保留min(c[x], d[x])值
    c1&c2
    # Counter({'a': 1, 'b': 2})
    
    ## 并集:  保留所有key键的并保留max(c[x], d[x])值
    c1|c2
    Counter({'a': 2, 'b': 3, 'd': 1, 'e': 5})
    
    #也只保留计数为正数的元素

    其他操作

    sum(c.values())  # 所有计数的总数
    c.clear()  # 重置Counter对象,注意不是删除
    list(c)  # 将c中的键转为列表=》由tuple构成的list
    set(c)  # 将c中的键转为set
    dict(c)  # 将c中的键值对转为字典
    c.items()  # 转为(elem, cnt)格式的列表
    Counter(dict(list_of_pairs))  # 从(elem, cnt)格式的列表转换为Counter类对象
    c.most_common()[:-n:-1]  # 取出计数最少的n个元素
    c += Counter()  # 移除0和负值
  • 相关阅读:
    内存分配小问题
    从MACHINE_START开始
    Linux驱动学习(二)
    9,斐波那契数列 6,旋转数组找最小 8青蛙跳台阶 JAVA实现
    数组练习题
    类的练习
    for循环练习题
    封装练习题
    Facebook成为Apache基金会的白金赞助商
    Visual Studio 2010
  • 原文地址:https://www.cnblogs.com/wqbin/p/10220488.html
Copyright © 2011-2022 走看看