Skip to content

Latest commit

 

History

History
141 lines (110 loc) · 4.74 KB

File metadata and controls

141 lines (110 loc) · 4.74 KB

Python 之OrderedDict模块

1. 是什么

OrderedDict模块是可以创建一个有顺序的字典。

2. 怎么用
from collections import OrderedDict
3. 有哪些方法
4. 举例说明
from collections import OrderedDict

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])

当你想要构建一个将来需要序列化或编码成其他格式的映射的时候,OrderedDict 是非常有用的。 比如,你想精确控制以 JSON 编码后字段的顺序,你可以先使用 OrderedDict 来构建这样的数据:

>>> import json
>>> json.dumps(d)
'{"foo": 1, "bar": 2, "spam": 3, "grok": 4}'
>>>

OrderedDict 内部维护着一个根据键插入顺序排序的双向链表。每次当一个新的元素插入进来的时候, 它会被放到链表的尾部。对于一个已经存在的键的重复赋值不会改变键的顺序。

需要注意的是,一个 OrderedDict 的大小是一个普通字典的两倍,因为它内部维护着另外一个链表。 所以如果你要构建一个需要大量 OrderedDict 实例的数据结构的时候(比如读取 100,000 行 CSV 数据到一个 OrderedDict 列表中去), 那么你就得仔细权衡一下是否使用 OrderedDict 带来的好处要大过额外内存消耗的影响。

为了寻找两个字典的相同点,可以简单的在两字典的 keys() 或者 items() 方法返回结果上执行集合操作。比如:

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

这些操作也可以用于修改或者过滤字典元素。 比如,假如你想以现有字典构造一个排除几个指定键的新字典。 下面利用字典推导来实现这样的需求:

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

一个字典就是一个键集合与值集合的映射关系。 字典的 keys() 方法返回一个展现键集合的键视图对象。 键视图的一个很少被了解的特性就是它们也支持集合操作,比如集合并、交、差运算。 所以,如果你想对集合的键执行一些普通的集合操作,可以直接使用键视图对象而不用先将它们转换成一个 set。

删除序列相同元素并保持顺序

如果序列上的值都是 hashable 类型,那么可以很简单的利用集合或者生成器来解决这个问题。比如:

>>> def dedupe(items):
...     seen = set()
...     for item in items:
...             if item not in seen:
...                     yield item
...                     seen.add(item)
... 
>>> a = [1,5,2,1,9,1,5,10]
>>> list(dedupe(a))
[1, 5, 2, 9, 10]

这个方法仅仅在序列中元素为 hashable 的时候才管用。 如果你想消除元素不可哈希(比如 dict 类型)的序列中重复元素的话,你需要将上述代码稍微改变一下,就像这样:

>>> def dedupe(items, key=None):
...     seen = set()
...     for item in items:
...             val = item if key is None else key(item)
...             if val not in seen:
...                     yield item
...                     seen.add(val)
... 
>>> a = [{'x':1, 'y':2},{'x':1, 'y':3},{'x':1, 'y':2},{'x':2, 'y':4}]
>>> list(dedupe(a, key=lambda d: (d['x'], d['y'])))
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
>>> list(dedupe(a, key=lambda d: d['x']))
[{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]

一般来讲,代码中如果出现大量的硬编码下标会使得代码的可读性和可维护性大大降低。 比如,如果你回过来看看一年前你写的代码,你会摸着脑袋想那时候自己到底想干嘛啊。 这是一个很简单的解决方案,它让你更加清晰的表达代码的目的。

内置的 slice() 函数创建了一个切片对象。

你还可以通过调用切片的 indices(size) 方法将它映射到一个已知大小的序列上。 这个方法返回一个三元组 (start, stop, step) ,所有的值都会被缩小,直到适合这个已知序列的边界为止。 这样,使用的时就不会出现 IndexError 异常。

>>> s='HelloWorld'
>>> a=slice()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: slice expected at least 1 arguments, got 0
>>> a=slice(2)
>>> a.indices(len(s))
(0, 2, 1)
>>> a=slice(5,50,2)
>>> a.indices(len(s))
(5, 10, 2)
>>> *a.indices(s)
  File "<stdin>", line 1
SyntaxError: can't use starred expression here
>>> for i in range(*a.indices(len(s))):
...     print(s[i])
... 
W
r
d