首页 > 代码库 > 数据结构相关模块(字典)

数据结构相关模块(字典)

1.多值映射

一般的字典都是一个键对应一个值。为了想要实现多值映射就需要一个容器,列表或者集合,比如:

d = {‘a‘ : [1, 2, 3],‘b‘ : [4, 5]}e = {‘a‘ : {1, 2, 3},‘b‘ : {4, 5}}

如果要实现上面的,就必须先对键值进行初始化为列表或者集合:

d={}
d.setdefault(‘a‘, []).append(1)

如果我们用collections模块下的defaultdict来实现就简单好多

d = defaultdict(list)for key, value in pairs:
    d[key].append(value)

如果自己实现呢?就是这样的:

d = {}for key, value in pairs:if key not in d:
    d[key] = []
    d[key].append(value)

2.字典排序

如果需要生成一个有顺序的字典,可以使用collections模块中的OrderedDict,会按照输入的顺序排序:

from collections import OrderedDictdef ordered_dict():
    d = OrderedDict()
    d[‘foo‘] = 1
    d[‘bar‘] = 2
    d[‘spam‘] = 3
    d[‘grok‘] = 4
    # Outputs "foo 1", "bar 2", "spam 3", "grok 4"
    for key in d:print(key, d[key])

当然,一个OrseredDict的大小是一个普通字典的两倍,因为它内部维护着另外一条链表

3.字典计算

当求最大值,最小值或者排序时,通常用到zip()函数将键和值翻转,然后进行比较或者排序

prices = {‘ACME‘: 45.23,‘AAPL‘: 612.78,‘IBM‘: 205.55,‘HPQ‘: 37.20,‘FB‘: 10.75}
min(zip(prices.values(),prices.keys()))
sorted(zip(prices.values(),prices.keys()))

注:zip函数创建的是一个只能访问一次的迭代器

prices_and_names = zip(prices.values(), prices.keys())print(min(prices_and_names)) # OKprint(max(prices_and_names)) # ValueError: max() arg is an empty sequence

也可以在 min() 和 max() 函数中提供 key 函数参数来获取最小值或最大值对应的键的信息

min(prices, key=lambda k: prices[k]) # Returns ‘FB‘

4.找两个字典的相同点

a = {‘x‘ : 1,‘y‘ : 2,‘z‘ : 3}b = {‘w‘ : 10,‘x‘ : 11,‘y‘ : 2}
a.keys() & b.keys() # { ‘x‘, ‘y‘ }
a.keys() - b.keys() # { ‘z‘ }
a.items() & b.items() # { (‘y‘, 2) }

字典过滤:

c = {key:a[key] for key in a.keys() - {‘z‘, ‘w‘}}# c is {‘x‘: 1, ‘y‘: 2}

字典的items()keys()都支持集合操作交,并,差运算~

5.根据某个或某几个字典字段来排序这个列表

通过使用 operator 模块的 itemgetter 函数,可以非常容易的排序这样的数据结构。

rows = [{‘fname‘: ‘Brian‘, ‘lname‘: ‘Jones‘, ‘uid‘: 1003},{‘fname‘: ‘David‘, ‘lname‘: ‘Beazley‘, ‘uid‘: 1002},{‘fname‘: ‘John‘, ‘lname‘: ‘Cleese‘, ‘uid‘: 1001},{‘fname‘: ‘Big‘, ‘lname‘: ‘Jones‘, ‘uid‘: 1004}]from operator import itemgetter
rows_by_fname = sorted(rows, key=itemgetter(‘fname‘))
rows_by_lfname = sorted(rows, key=itemgetter(‘lname‘,‘fname‘))

当然也可以用匿名函数代替itemgetter(),但是,使用itemgetter()方式会运行的稍微快点 ``` rowsbyfname = sorted(rows, key=lambda r: r[‘fname‘]) rowsbylfname = sorted(rows, key=lambda r: (r[‘lname‘],r[‘fname‘]))

以上同样适用于min() max()### 6排序不支持原生比较的对象 operator.attrgetter()

class User: def init(self, userid): self.userid = userid def repr(self): return ‘User({})‘.format(self.userid) def sortnotcompare(): users = [User(23), User(3), User(99)] print(users) print(sorted(users, key=lambda u: u.userid)) ```

另外一种方式是使用 operator.attrgetter() 来代替lambda函数:

>>> from operator import attrgetter>>> sorted(users, key=attrgetter(‘user_id‘))
[User(3), User(23), User(99)]

7.通过某字段分组

groupby() 函数扫描整个序列并且查找连续相同值(或者根据指定key函数返回值相同)的元素序列。 首先需要按照指定的字段(这里就是 date )排序, 然后调用 itertools.groupby() 函数:

from operator import itemgetterfrom itertools import groupby# Sort by the desired field firstrows.sort(key=itemgetter(‘date‘))# Iterate in groupsfor date, items in groupby(rows, key=itemgetter(‘date‘)):
    print(date)    for i in items:
        print(‘ ‘, i)

8.合并多个字典

一个非常简单的解决方案就是使用 collections 模块中的 ChainMap 类 一个 ChainMap 接受多个字典并将它们在逻辑上变为一个字典。 然后,这些字典并不是真的合并在一起了, ChainMap 类只是在内部创建了一个容纳这些字典的列表 并重新定义了一些常见的字典操作来遍历这个列表。大部分字典操作都是可以正常使用的 作为 ChainMap 的替代,你可能会考虑使用 update() 方法将两个字典合并。但是它需要你创建一个完全不同的字典对象(或者是破坏现有字典结构)。 同时,如果原字典做了更新,这种改变不会反应到新的合并字典中去。


本文出自 “机制小风风” 博客,请务必保留此出处http://xiaofengfeng.blog.51cto.com/8193303/1885782

数据结构相关模块(字典)