1.10 åˆ é™¤åº�列相å�Œå…ƒç´ å¹¶ä¿�æŒ�顺åº�¶
问题¶
æ€Žæ ·åœ¨ä¸€ä¸ªåº�列上é�¢ä¿�æŒ�å…ƒç´ é¡ºåº�çš„å�Œæ—¶æ¶ˆé™¤é‡�å¤�的值?
解决方案¶
如果�列上的值都是 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)
这里的keyå�‚数指定了一个函数,将åº�åˆ—å…ƒç´ è½¬æ�¢æˆ� hashable 类型。下é�¢æ˜¯å®ƒçš„用法示例:
>>> 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}]
>>>
å¦‚æžœä½ æƒ³åŸºäºŽå�•ä¸ªå—æ®µã€�属性或者æŸ�个更大的数æ�®ç»“æž„æ�¥æ¶ˆé™¤é‡�å¤�å…ƒç´ ï¼Œç¬¬äºŒç§�方案å�Œæ ·å�¯ä»¥èƒœä»»ã€‚
讨论¶
å¦‚æžœä½ ä»…ä»…å°±æ˜¯æƒ³æ¶ˆé™¤é‡�å¤�å…ƒç´ ï¼Œé€šå¸¸å�¯ä»¥ç®€å�•çš„æž„é€ ä¸€ä¸ªé›†å�ˆã€‚比如:
>>> a
[1, 5, 2, 1, 9, 1, 5, 10]
>>> set(a)
{1, 2, 10, 5, 9}
>>>
然而,这ç§�方法ä¸�èƒ½ç»´æŠ¤å…ƒç´ çš„é¡ºåº�,生æˆ�的结果ä¸çš„å…ƒç´ ä½�置被打乱。而上é�¢çš„æ–¹æ³•å�¯ä»¥é�¿å…�è¿™ç§�情况。
åœ¨æœ¬èŠ‚ä¸æˆ‘们使用了生æˆ�å™¨å‡½æ•°è®©æˆ‘ä»¬çš„å‡½æ•°æ›´åŠ é€šç”¨ï¼Œä¸�仅仅是局é™�于列表处ç�†ã€‚ æ¯”å¦‚ï¼Œå¦‚æžœå¦‚æžœä½ æƒ³è¯»å�–一个文件,消除é‡�å¤�è¡Œï¼Œä½ å�¯ä»¥å¾ˆå®¹æ˜“åƒ�è¿™æ ·å�šï¼š
with open(somefile,'r') as f:
for line in dedupe(f):
...
上述key函数å�‚数模仿了 sorted() , min() å’Œ max() ç‰å†…置函数的相似功能。
�以�考 1.8 和 1.13 �节了解更多。