Python - 从复杂对象的有序列表中删除重复项?

问题描述 投票:0回答:3

我有以下形式从json生成的数百万字典的列表:

{
  "_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变种不允许访问项目的索引?在Python中有没有类似的简短方法来完成这样的事情?我发现sorted(...)函数允许我按照我想要的方式对这个列表进行排序,但是我仍然不知道如何过滤掉下面的重复项(没有明显的,粗暴的循环)。

python algorithm
3个回答
2
投票

使用字典删除重复项(这将始终保持每个_id的最后一次出现):

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

然后按_id对其值进行排序:

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

2
投票

python中的惯用方法是:

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]

注意,内置的python 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                 

您可以使用python匿名函数和三元运算符(在Python中,使用“条件表达式”)创建javascript的音译。注意,Python的sorted函数不使用比较器函数,它使用key-based function

key指定一个参数的函数,该函数用于从每个列表元素中提取比较键:key=str.lower。默认值为None(直接比较元素)。

在Python 2中,仍然可以使用与Javascript版本类似的cmp参数(例如,返回-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'}]
© www.soinside.com 2019 - 2024. All rights reserved.