一般来说字典中是一个键对应一个单值的映射,如果想一个键值映射多个值,那么就需要将这些值放到另外的容器中,比如列表或者集合。

比如d={'a':[1,2]}
Collections中的defaultdict模块会自动创建这样的字典。如下
d=defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(3)
defaultdict(<type 'list'>, {'a': [1, 2], 'b': [3]})
下面再来看下字典的排序
d={}
d['foo']=1
d['bar']=2
d['span']=3
d['grok']=4
print d
for key in d:
    print key,d[key]
输出:
{'span': 3, 'foo': 1, 'bar': 2, 'grok': 4}
span 3
foo 1
bar 2
grok 4
可以看到无论是直接打印d还是遍历d,输出的值都是无序的。和数据的写入的顺序无关。那么OrderedDict可以生成根据键插入顺序的字典。
d=OrderedDict()
d['foo']=3
d['bar']=2
d['spam']=4
print d
for key in d:
    print key,d[key]
输出:
OrderedDict([('foo', 3), ('bar', 2), ('spam', 4)])
foo 3
bar 2
spam 4
可以看到遍历字典的时候是根据键值生成顺序来排序的。是因为OrderedDict内部是生成一个链表的形式,新增加的元素都放到链表末端
 
字典的最大值最小值计算
a={}
a['foo']=3
a['bar']=2
a['spam']=4
print max(a)
这个比较结果是将字段的键值进行比较,然后输出一个最大值。如果要根据值来取最大,最小值,可以用max(a.values())的方法。如果要进一步反馈出对应的键值。可以用zip函数先将字典的键和值进行反转。
max(zip(a.values(),a.keys()))
zip函数的作用是将括号的参数形成一个tuple列表。通过翻转以后。列表中value在前,键值在后。因此进行比较的时候首先比较值。输出如下:
(4, 'spam')
 
找到一个序列中出现次数最多的元素:
经常在字符处理和文本处理中会遇到找次数最多的元素。如果一个个的去遍历太耗时间。这里可以用collections.Counter来达到这个目的
words=['look','info','my','look','into','eys','my','eyes','the','look','around','eyes','the','eys']
word_count=Counter(words)
print word_count
print word_count['look']
结果如下:
Counter({'look': 3, 'eyes': 2, 'eys': 2, 'the': 2, 'my': 2, 'info': 1, 'into': 1, 'around': 1})
3
从结果中可以看出,Counter就是将字符串做成了一个字典的形式,依次列出了各个元素出现的次数,并且是降序排列。从Counter的定义来看,可以看出也是继承自dict的
class Counter(dict):
另外可以认为的改变出现的次数word_count['look']+=1。这个时候look的次数就会变成4次,但是实际打印原字符串还是原来的字符串。
words=['look','info','my','look','into','eys','my','eyes','the','look','around','eyes','the','eys']
c=word_count=Counter(words)
word_count['look']+=1
print words
print word_count['look']
['look', 'info', 'my', 'look', 'into', 'eys', 'my', 'eyes', 'the', 'look', 'around', 'eyes', 'the', 'eys']
4
这是怎么回事呢。我们首先来看下Counter的初始化说明:可以看到__init__是创建一个新的空的counter对象。如果有输入则通过输入进行元素的初始化

words=['look','info','my','look','into','eys','my','eyes','the','look','around','eyes','the','eys']
c=word_count=Counter(words)
d=[e for e in c.elements()]
print d
print words
 
wo打印如下,可以看到除了顺序被改变之外,元素都一样的
['info', 'eyes', 'eyes', 'look', 'look', 'look', 'into', 'eys', 'eys', 'the', 'the', 'my', 'my', 'around']
['look', 'info', 'my', 'look', 'into', 'eys', 'my', 'eyes', 'the', 'look', 'around', 'eyes', 'the', 'eys']
现在回到我们之前的问题word_count['look']+=1 后words并没有被改变。那么被改变的肯定是新生成的对象。那么测试一下:
words=['look','info','my','look','into','eys','my','eyes','the','look','around','eyes','the','eys']
c=word_count=Counter(words)
word_count['look']+=1
d=[e for e in c.elements()]
print d
输出结果如下,可以看到确实增加了一个look。证明了后续的操作都是新增对象上进行操作的。
['info', 'eyes', 'eyes', 'look', 'look', 'look', 'look', 'into', 'eys', 'eys', 'the', 'the', 'my', 'my', 'around']
我们再来看另外一个update的用法。同样的我们首先看下这个函数的定义说明
Add counts instead of replace them。意思是将一个元素增加到新增的元素上面

word_count.update(words)
d=[e for e in c.elements()]
print d
print c
 
结果如下。可以看到是将words添加到了c这个新对象中去。因此计数也在之前的基础上增加了2倍
['info', 'info', 'eyes', 'eyes', 'eyes', 'eyes', 'look', 'look', 'look', 'look', 'look', 'look', 'into', 'into', 'eys', 'eys', 'eys', 'eys', 'the', 'the', 'the', 'the', 'my', 'my', 'my', 'my', 'around', 'around']
Counter({'look': 6, 'eyes': 4, 'eys': 4, 'the': 4, 'my': 4, 'info': 2, 'into': 2, 'around': 2})
 
在看Counter的源代码的时候,注意到还有下面的数学运算功能:
def __add__(self, other):
def __sub__(self, other):
这意味着可以在对象上进行加,减操作
words1=['abc','def']
words2=['ghi','jkm','abc']
a=Counter(words1)
b=Counter(words2)
print a+b
print a-b
输出结果如下:想减则意味着去掉重复的元素
Counter({'abc': 2, 'jkm': 1, 'ghi': 1, 'def': 1})
Counter({'def': 1})
 
 
通过某个关键字对字典进行排序:
可以采用itemgetter的方法。代码如下。用sorted进行排序,并设置比较关键参数key=itemgetter()
from operator import itemgetter
rows=[{'fname':'Brian','lname':'Jones','uid':1003},
      {'fname':'David','lname':'Beazley','uid':1002},
      {'fname':'John','lname':'Cleeze','uid':1001},
      {'fname':'Big','lname':'Jones','uid':1004}]
rows_by_uid=sorted(rows,key=itemgetter('uid'))
rows_by_name=sorted(rows,key=itemgetter('fname'))
print rows_by_uid
print rows_by_name

我们来看下这个函数是如何工作的。首先我们用lambda来改造下这个功能
rows_by_uid1=sorted(rows,key=lambda r:r['uid'])
print rows_by_uid1。可以看到得到的结果和sorted(rows,key=itemgetter('uid'))是一样的

证明可以用lambda是可以达到同样的效果。首先sorted函数是接受一个可迭代的对象,然后从rows中接受一个单一的元素.如rows[0],rows[1],rows[2],rows[3]各个字典。这个字典传入itemgetter,并根据传入的参数返回字典的值。从下面的定义可以更好的理解。

其实可以用列表本身的sort函数也是可以达到同样的效果:
rows.sort(key=lambda r:r['uid'])
print rows

两种方法的速度谁更快一点呢,其实如果数据不多的话,都差不多。数据量大的话网上推荐用itemgetter。
下面来看另外一个列子,对于实例中的参数进行排序:
 
class user():
    def __init__(self,id):
        self.userid=id
    def __repr__(self):
        return 'user({})'.format(self.userid)
UE=[user(23),user(46),user(12)]
print UE
print sorted(UE,key=attrgetter('userid'))
结果如下:

这里用到了attrgetter。通过下面的介绍我们可以看到这个主要是从实例中取出关键数据

下面再来看下对字典进行分类的函数:
数据如下,如果想按照date函数进行归类,也就是相同date的归为一类
rows = [
{'address': '5412 N CLARK', 'date': '07/01/2012'},
{'address': '5148 N CLARK', 'date': '07/04/2012'},
{'address': '5800 E 58TH', 'date': '07/02/2012'},
{'address': '2122 N CLARK', 'date': '07/03/2012'},
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
{'address': '1060 W ADDISON', 'date': '07/02/2012'},
{'address': '4801 N BROADWAY', 'date': '07/01/2012'},
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]
    rows.sort(key=itemgetter('date'))
    for date,item in groupby(rows,itemgetter('date')):
        print date
        for i in item:
            print i
结果如下,可以看到同样的日期被归成了一类

Groupby通过查找连续相同的值,并返回值相同的对象。这里有一点需要注意,因为groupby是查找连续的值,所以要想得到想要的结果。必须先排序,如果不排序的话,得到的结果则是错误的。下面就是未排序的结果。从结果中明显可以看出groupby是查找连续相同的值来归类的。由于未排序,导致结果是零散的。

其实groupby就是一个归类函数,可以理解为同一个字典键值映射多个值。我们是否可以用前面介绍的defaultdict来构造呢。答案是可以的,因为dafaultdict可以将键值相同的值归为一类,也可以实现groupby的功能
rows_by_date=defaultdict(list)
for row in rows:
    print row
    rows_by_date[row['date']].append(row)
    print rows_by_date
E:\python2.7.11\python.exe E:/py_prj/python_cookbook.py
{'date': '07/01/2012', 'address': '5412 N CLARK'}
defaultdict(<type 'list'>, {'07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}]})
 
{'date': '07/04/2012', 'address': '5148 N CLARK'}
defaultdict(<type 'list'>, {'07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}], '07/04/2012': [{'date': '07/04/2012', 'address': '5148 N CLARK'}]})
 
{'date': '07/02/2012', 'address': '5800 E 58TH'}
defaultdict(<type 'list'>, {'07/02/2012': [{'date': '07/02/2012', 'address': '5800 E 58TH'}], '07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}], '07/04/2012': [{'date': '07/04/2012', 'address': '5148 N CLARK'}]})
 
{'date': '07/03/2012', 'address': '2122 N CLARK'}
defaultdict(<type 'list'>, {'07/02/2012': [{'date': '07/02/2012', 'address': '5800 E 58TH'}], '07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}], '07/04/2012': [{'date': '07/04/2012', 'address': '5148 N CLARK'}], '07/03/2012': [{'date': '07/03/2012', 'address': '2122 N CLARK'}]})
 
{'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}
defaultdict(<type 'list'>, {'07/02/2012': [{'date': '07/02/2012', 'address': '5800 E 58TH'}, {'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}], '07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}], '07/04/2012': [{'date': '07/04/2012', 'address': '5148 N CLARK'}], '07/03/2012': [{'date': '07/03/2012', 'address': '2122 N CLARK'}]})
 
{'date': '07/02/2012', 'address': '1060 W ADDISON'}
defaultdict(<type 'list'>, {'07/02/2012': [{'date': '07/02/2012', 'address': '5800 E 58TH'}, {'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}, {'date': '07/02/2012', 'address': '1060 W ADDISON'}], '07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}], '07/04/2012': [{'date': '07/04/2012', 'address': '5148 N CLARK'}], '07/03/2012': [{'date': '07/03/2012', 'address': '2122 N CLARK'}]})
 
{'date': '07/01/2012', 'address': '4801 N BROADWAY'}
defaultdict(<type 'list'>, {'07/02/2012': [{'date': '07/02/2012', 'address': '5800 E 58TH'}, {'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}, {'date': '07/02/2012', 'address': '1060 W ADDISON'}], '07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}, {'date': '07/01/2012', 'address': '4801 N BROADWAY'}], '07/04/2012': [{'date': '07/04/2012', 'address': '5148 N CLARK'}], '07/03/2012': [{'date': '07/03/2012', 'address': '2122 N CLARK'}]})
 
{'date': '07/04/2012', 'address': '1039 W GRANVILLE'}
defaultdict(<type 'list'>, {'07/02/2012': [{'date': '07/02/2012', 'address': '5800 E 58TH'}, {'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}, {'date': '07/02/2012', 'address': '1060 W ADDISON'}], '07/01/2012': [{'date': '07/01/2012', 'address': '5412 N CLARK'}, {'date': '07/01/2012', 'address': '4801 N BROADWAY'}], '07/04/2012': [{'date': '07/04/2012', 'address': '5148 N CLARK'}, {'date': '07/04/2012', 'address': '1039 W GRANVILLE'}], '07/03/2012': [{'date': '07/03/2012', 'address': '2122 N CLARK'}]})
 
这样我们可以轻松的通过下面的方式来进行查找某个日期的信息。
for i in rows_by_date['07/01/2012']:
    print i

那么我们用哪一种方式更好呢。从时间效率上来看,groupby的方式更快一些,下面是做了一个时间上的对比,可以看到多次运行都是groupby占优








												

python cookbook第三版学习笔记二:字典的更多相关文章

  1. python cookbook第三版学习笔记二十:可自定义属性的装饰器

    在开始本节之前,首先介绍下偏函数partial.首先借助help来看下partial的定义 首先来说下第一行解释的意思: partial 一共有三个部分: (1)第一部分也就是第一个参数,是一个函数, ...

  2. python cookbook第三版学习笔记二十一:利用装饰器强制函数上的类型检查

    在演示实际代码前,先说明我们的目标:能对函数参数类型进行断言,类似下面这样: @typeassert(int, int) ... def add(x, y): ...     return x + y ...

  3. python cookbook第三版学习笔记十:类和对象(一)

    类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair:     def __init__(self,x,y):         self.x=x         self. ...

  4. python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法

    在子类中调用父类的方法,可以下面的A.spam(self)的方法. class A(object):     def spam(self):         print 'A.spam' class ...

  5. python cookbook第三版学习笔记十二:类和对象(三)创建新的类或实例属性

    先介绍几个类中的应用__getattr__,__setattr__,__get__,__set__,__getattribute__,. __getattr__:当在类中找不到attribute的时候 ...

  6. python cookbook第三版学习笔记 一

    数据结构 假设有M个元素的列表,需要从中分解出N个对象,N<M,这会导致分解的值过多的异常.如下: record=['zhf','zhf@163.com','775-555-1212','847 ...

  7. python cookbook第三版学习笔记十三:类和对象(三)描述器

    __get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...

  8. python cookbook第三版学习笔记七:python解析csv,json,xml文件

    CSV文件读取: Csv文件格式如下:分别有2行三列. 访问代码如下: f=open(r'E:\py_prj\test.csv','rb') f_csv=csv.reader(f) for f in ...

  9. python cookbook第三版学习笔记六:迭代器与生成器

    假如我们有一个列表 items=[1,2,3].我们要遍历这个列表我们会用下面的方式 For i in items:   Print i 首先介绍几个概念:容器,可迭代对象,迭代器 容器是一种存储数据 ...

随机推荐

  1. asp.net上传文件夹权限配置以及权限配置的分析

    切记:一定要禁止给公共上传文件夹的权限设置为everyone,且为完全控制!除非你这个文件夹属于内部操作的,那这样做是允许,其余情况一律禁止! 基本的文件上传文件夹权限配置: 1.在需要配置上传的文件 ...

  2. 非常有用的开发工具之Android Studio插件

    我们都知道Eclipse开发Android将在今年年底google不再继续提供相应的开发支持,转而开始强烈发展Android Studio,现在我就分享几款能帮助团队提升工作效率的几个Android ...

  3. 【ecplise】快捷键 集合

    1.查看本方法在哪里被调用过 光标放在本方法名上 快捷键: Ctrl+Shift+G

  4. 2017.2.28 activiti实战--第五章--用户与组及部署管理(二)部署流程资源

    学习资料:<Activiti实战> 第五章 用户与组及部署管理(二)部署流程资源 内容概览:讲解流程资源的读取与部署. 5.2 部署流程资源 5.2.1 流程资源 流程资源常用的有以下几种 ...

  5. Mysql 性能监控及调优

    死锁概念: 两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象 1.监控死锁(innotop): (1) 启用 innodb_status_file 在/etc/my.cnf添加如 ...

  6. 模拟利器Mockito

    16.3.1  模拟测试概述 目前支持Java语言的Mock测试工具有EasyMock.JMock.Mockito.MockCreator.Mockrunner.MockMaker等,Mockito是 ...

  7. mysql 导入sql文件时编码报错

    1.命令行导入 mysql -uroot -pnewpwd --default-character-set=utf8 databasename < xxx.sql 2.使用source导入 进入 ...

  8. websocket关于禁止一个账号多窗口链接的问题

    通过websocket的session.getSessionId()与oldSession.getSessionId()来equals判断是否是新窗口. 如果不同不让链接. 问题1.虽然新来的链接连不 ...

  9. UNP学习笔记(第三章:套接字编程简介)

    本章开始讲解套接字API. 套接字地址结构 IPv4套接字地址结构 它以sockaddr_in命名,下面给出它的POSIX定义 struct in_addr { in_addr_t s_addr; } ...

  10. 利用window.navigator.userAgent判断当前是否微信内置浏览器

    <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="utf-8&quo ...