2017-12-27 229 views
0

我從JSON形式產生這樣的字典幾個milions的名單:Python - 從複雜對象的有序列表中刪除重複項?

{ 
    "_id":XXX, 
    "some_other":"fields", 
    ... 
} 

列表必須是安全的排序由_id關鍵但也有與重複_id disctionaries。與列表大小(最多大約10-100)相比,實際上很少有重複項。我只想爲每個重複的_id只取第一個(或最後一個,只要它是確定性的)字典。在JavaScript中我會使用下列內容:

list.sort((a,b)=>a._id>b._id?1:(a._id<b._id?-1:0)) 
    .filter((ent,i,arr)=>i==0||ent!=arr[i-1]) 

但是我想過濾的蟒蛇變種不允許訪問項目的索引?在Python中有沒有類似的簡短方法來完成這樣的事情?我發現sorted(...)函數允許我以我想要的方式對這個列表進行排序,但是我仍然不知道如何濾除以下重複項(沒有明顯的,粗暴的for循環)。

+0

你看着'sorted'和'filter'?Python有'map','filter'和'reduce'結構,你可以使用'lambda args:'來編寫一個等效的表達式,它使用Python的(有點笨拙的)匿名函數語法。儘管如此,對於過濾/映射,經常列表理解(和相關構造,例如'詞典'理解,'集合'理解甚至生成器表達式)被認爲更習慣。 –

回答

2

使用字典來刪除重複項(這將始終保持對每個_id最後一次出現):

d = {i['_id']: i for i in your_list} 

然後排序它的值由_id:

list(sorted(d.values(), key=lambda i: i['_id'])) 
2

的慣用方式,蟒蛇,將是:

import itertools 
import operator 

get_id = operator.itemgetter('_id') #factory function: lambda x:x['_id'] 
grouped = itertools.groupby(sorted(json_data, key=get_id), get_id) 

result = [next(g) for k,g in grouped] 

注意,內置的蟒蛇sorted是一個穩定的排序,使用一個名爲timsort的自適應合併類。

itertools是一個非常有用的模塊,有效地實現了各種惰性迭代器。 groupby是一個組的迭代器:

# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B 
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D     

您可以創建你的JavaScript的音譯,使用python匿名函數和三元操作符(在Python中,「條件表達式」)。注意,Python的sorted功能不使用比較器功能,它採用了key-based function

鍵指定用於提取從每個列表元素的 比較關鍵的一個參數的函數:key=str.lower。默認 的值是None(直接比較元素)。

在Python 2,一個cmp論點,即工作方式類似於給Javascript版本仍然是可用的(例如,它返回-1,1或0的函數)

cmp被棄用,最後在Python 3除去贊成key

1

使用sortedfiltermap

d = [ 
    { 
     "_id": 3, 
     "some_other": "a" 
    }, 
    { 
     "_id": 1, 
     "some_other": "b" 
    }, 
    { 
     "_id": 2, 
     "some_other": "c" 
    }, 
    { 
     "_id": 2, 
     "some_other": "d" 
    } 
] 

sorted_d = sorted(d, key=lambda x: x['_id']) 
map(
    lambda y: y[1], 
    filter(
     lambda x: True if x[0]==0 else sorted_d[x[0]]["_id"] != sorted_d[x[0]-1]["_id"], 
     enumerate(sorted_d) 
    ) 
) 

輸出:

[{'_id': 1, 'some_other': 'b'}, 
{'_id': 2, 'some_other': 'c'}, 
{'_id': 3, 'some_other': 'a'}]