2017-12-27 203 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'}]