python 有序字典

有序字典实现
#coding=utf-8
#实现一个有序字典类

import bisect
class OrderedDict(object):

	def __init__(self, dictionary = None):
		self.__keys = []
		self.__dict = {}
		if dictionary is not None:
			if isinstance(dictionary, OrderedDict):
				self.__dict = dictionary.__dict.copy()
				self.__keys = dictionary.__keys[:]
			else:
				self.__dict = dict(dictionary).copy()
				self.__keys = sorted(self.__dict.keys())

	def getAt(self, index):
		return self.__dict[self.__keys[index]]

	def setAt(self, index, value):
		self.__dict[self.__keys[index]] = value
	
	def __getitem__(self, key):
		return self.__dict[key]

	def __setitem__(self, key, value):
		if key not in self.__dict:
			bisect.insort_left(self.__keys, key)
		self.__dict[key] = value
	
	def __delitem__(self, key):
		i = bisect.bisect_left(self.__keys, key)
		del self.__keys[i]
		del self.__dict[key]
	
	def get(self, key, value = None):
		return self.__dict.get(key, value)

	def setdefault(self, key, value):
		if key not in self.__dict:
			bisect.insort_left(self.__keys, key)
		return self.__dict.setdefault(key, value)

	def pop(self, key, value = None):
		if key not in self.__dict:
			return value
		i = bisect.bisect_left(self.__keys, key)
		del self.__keys[i]
		return self.__dict.pop(key, value)

	def popitem(self):
		item = self.__dict.popitem()
		i = bisect.bisect_left(self.__keys, item[0])
		del self.__keys[i]
		return item

	def has_key(self, key):
		return key in self.__dict

	def __contains__(self, key):
		return key in self.__dict

	def __len__(self):
		return len(self.__dict)

	def keys(self):
		return self.__keys[:]

	def values(self):
		return [self.__dict[key] for key in self.__keys]
	
	def items(self):
		return [(key, self.__dict[key]) for key in self.__keys]

	def __item__(self):
		return iter(self.__keys)

	def __iterkeys(self):
		return iter(self.__keys)

	def itervalues(self):
		for key in  self.__keys:
			yield self.__dict[key]
	
	def iteritems(self):
		for key in self.__keys:
			yield key, self.__dict[key]

	def copy(self):
		dictionary = OrderedDict()
		dictionary.__keys = self.keys[:]
		dictionary.__dict = self.__dict.copy()
		return dictionary

	def clear(self):
		self.__keys = []
		self.__dict = {}
	
	def _repr__(self):
		pieces = []
		for key in self.__keys:
			pieces.append("%r: %r" % (key, self.__dict[key]))
		return "OrderedDict({%s})" % ", ".join(pieces)

d = OrderedDict(dict(s=1, a=2, n=3, i=4, t=5))
for i in d.keys():
	print i
`d`


<think>我们正在讨论Python中的有序字典(Ordered Dictionary),具体是指`collections.OrderedDict`。以下内容将涵盖其基本用法、最佳实践以及一些高级技巧。 ### 1. 有序字典的基本概念 在Python 3.7之前,标准的字典(dict)不保证元素的顺序。但`collections.OrderedDict`自Python 3.1起就提供了保持插入顺序的功能。值得注意的是,从Python 3.7开始,标准字典也保持插入顺序,但`OrderedDict`仍然有一些额外的功能。 ### 2. 创建有序字典 ```python from collections import OrderedDict # 创建一个空的有序字典 od = OrderedDict() # 添加元素 od['a'] = 1 od['b'] = 2 od['c'] = 3 # 或者通过键值对列表创建 od = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) ``` ### 3. 关键特性 - **保持插入顺序**:当遍历有序字典时,元素按照它们被插入的顺序返回。 - **重新排序**:通过`move_to_end`方法可以将一个键移动到字典的末尾(或开头)。 ```python od.move_to_end('a') # 将键为'a'的元素移动到末尾 od.move_to_end('b', last=False) # 移动到开头 ``` - **相等性比较**:两个`OrderedDict`相等不仅要求键值对相同,还要求顺序相同。而普通字典只要求键值对相同(不考虑顺序)。 ### 4. 常用操作 #### 4.1 遍历 ```python for key in od: print(key, od[key]) # 或者 for key, value in od.items(): print(key, value) ``` #### 4.2 删除元素 ```python # 删除最后一个元素 od.popitem(last=True) # 默认删除并返回最后一个元素 # 删除开头元素 od.popitem(last=False) # 删除指定键 od.pop('a') ``` #### 4.3 更新元素 ```python od['a'] = 100 # 更新值,但位置不变 od.update({'a': 100, 'd': 4}) # 更新值,如果添加新键则放在末尾 ``` ### 5. 最佳实践 1. **何时使用`OrderedDict`?** - 当需要保持插入顺序,并且代码需要运行在Python 3.6以下版本时(因为3.6以下普通字典无序)。 - 当需要利用`move_to_end`方法重新排序元素时(普通字典没有这个方法)。 - 当需要顺序敏感的相等性比较时。 2. **性能考虑** - `OrderedDict`比普通字典占用更多内存(因为它内部维护了一个双向链表来记录顺序)。 - 操作的时间复杂度与普通字典相同($O(1)$),但常数因子更大。 3. **替代方案** - 如果使用Python 3.7+且不需要`move_to_end`等功能,普通字典就足够了。 - 对于需要频繁重新排序的场景,`OrderedDict`的`move_to_end`方法非常高效。 ### 6. 高级用法:实现LRU缓存 `OrderedDict`可以方便地实现LRU(最近最少使用)缓存: ```python class LRUCache: def __init__(self, capacity): self.cache = OrderedDict() self.capacity = capacity def get(self, key): if key not in self.cache: return -1 self.cache.move_to_end(key) # 访问后移动到末尾(表示最近使用) return self.cache[key] def put(self, key, value): if key in self.cache: self.cache.move_to_end(key) self.cache[key] = value if len(self.cache) > self.capacity: self.cache.popitem(last=False) # 删除最久未使用的元素(开头) ``` ### 7. 注意事项 - 在Python 3.8+中,`OrderedDict`支持`reversed()`逆序遍历。 - 从Python 3.9开始,`OrderedDict`支持合并运算符`|`和更新运算符`|=`。 §§相关问题§§ 1. Python 3.7+中普通字典已经有序,那么`OrderedDict`还有哪些不可替代的用途? 2. 如何将两个有序字典合并并保持顺序? 3. 在实现LRU缓存时,除了`OrderedDict`还有哪些替代方案? 4. 如何将普通字典转换为有序字典并保持当前顺序?</think>### Python 有序字典(OrderedDict)详解 #### 1. **核心概念** 有序字典 (`collections.OrderedDict`) 是 Python 标准库中的特殊字典类型,它**保持键的插入顺序**,与普通字典Python 3.6+ 后字典有序)的关键区别在于额外提供了顺序控制方法[^1]。 ```python from collections import OrderedDict # 创建有序字典 od = OrderedDict() od['z'] = 3 # 第一个插入 od['a'] = 1 # 第二个插入 od['c'] = 2 # 第三个插入 print(list(od.keys())) # 输出: ['z', 'a', 'c'] - 保持插入顺序 ``` #### 2. **主要特性** - **顺序保持**:元素按添加顺序迭代(Python 3.7前普通字典无序) - **顺序操作**:支持`move_to_end()`等顺序控制方法 - **相等性判断**:两个`OrderedDict`顺序不同则不相等(普通字典只比较内容) #### 3. **关键方法** ```python # 移动元素到末尾 od.move_to_end('z') # 将键'z'移到末尾 print(list(od)) # 输出: ['a', 'c', 'z'] # 移动元素到开头 od.move_to_end('c', last=False) # 移到开头 print(list(od)) # 输出: ['c', 'a', 'z'] # 弹出指定元素 val = od.pop('a') # 返回: 1 print(od) # OrderedDict([('c', 2), ('z', 3)]) # 弹出最后/最前元素 last = od.popitem(last=True) # ('z', 3) first = od.popitem(last=False) # ('c', 2) ``` #### 4. **最佳实践** 1. **LRU缓存实现**(最近最少使用) ```python class LRUCache: def __init__(self, capacity): self.cache = OrderedDict() self.capacity = capacity def get(self, key): if key not in self.cache: return -1 self.cache.move_to_end(key) # 标记为最近使用 return self.cache[key] def put(self, key, value): if key in self.cache: self.cache.move_to_end(key) self.cache[key] = value if len(self.cache) > self.capacity: self.cache.popitem(last=False) # 移除最久未使用 ``` 2. **配置文件解析**(保持参数顺序) ```python config = OrderedDict([ ('title', 'Main Settings'), ('version', 1.2), ('debug', False) ]) ``` 3. **JSON序列化保持顺序** ```python import json data = OrderedDict([('name', 'Alice'), ('age', 30), ('city', 'Paris')]) json_str = json.dumps(data) # 保持键的顺序 ``` 4. **高效合并字典(保留顺序)** ```python def merge_ordered_dicts(dict1, dict2): merged = OrderedDict() for d in [dict1, dict2]: for k, v in d.items(): if k not in merged: # 避免覆盖 merged[k] = v return merged ``` #### 5. **性能注意事项** - **空间开销**:比普通字典多约20-25%内存(维护双向链表) - **时间开销**: - 插入操作:$O(1)$ - 删除操作:$O(1)$ - `move_to_end()`:$O(1)$ - **适用场景**: - 需要顺序控制的配置/历史记录 - LRU缓存实现 - 需要顺序序列化的场景 - 旧版Python(<3.6)的有序存储 #### 6. **与普通字典比较** | 特性 | `OrderedDict` | Python 3.7+ 普通字典 | |--------------------|---------------------|----------------------| | 顺序保证 | ✅ 插入顺序 | ✅ 插入顺序 | | `move_to_end()` | ✅ | ❌ | | 顺序相等性判断 | ✅ (顺序敏感) | ❌ (顺序不敏感) | | 内存占用 | 较高 (多20-25%) | 较低 | | `popitem(last)` | ✅ 可指定方向 | ✅ 只能弹出最后项 | > **何时使用**:需要`move_to_end()`、顺序敏感相等性判断,或兼容Python 3.6以下版本[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值