在多个键集上过滤字典的python列表

时间:2019-02-18 18:48:54

标签: python

说我有字典:

SELECT  
SUM(IF(a.id = 1, IF(t.type = 1 AND t.charge_account = 1, t.value, 0) - IF(t.type = 0 AND t.charge_account = 1, t.value, 0), 0) + a.start-balance) as "balanc_1",
SUM(IF(a.id = 2, IF(t.type = 1 AND t.charge_account = 2, t.value, 0) - IF(t.type = 0 AND t.charge_account = 2, t.value, 0), 0) + a.start-balance) as "balance_2",
SUM(IF(a.id = 3, IF(t.type = 1 AND t.charge_account = 3, t.value, 0) - IF(t.type = 0 AND t.charge_account = 3, t.value, 0), 0) + a.start-balance) as "balance_3"
FROM test.transactions t, test.accounts a
WHERE t.paid = 1;

我有一个称为键的列表:

my_dict = [
        {'first': 'James', 'middle': 'Smith', 'last': 'Joule'}, 
        {'first': 'James', 'middle': 'smith', 'last': 'joule'},
        {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'},
        {'first': 'Robert', 'middle': 'Edward', 'last': 'Antonio'},
        {'first': 'Robert', 'middle': 'edward', 'last': 'antonio'},
        {'first': 'Robert', 'middle': 'edwrd', 'last': 'Antonio'},
        {'first': 'James', 'middle': 'Jackson', 'last': 'harden'}, 
        {'first': 'James', 'middle': 'jackson', 'last': 'Harden'},
      ]

我想根据键中的每个值过滤myDict,这将导致

keys = ["first", "last"]

正如您在my_dict列表中的列表字典中所观察到的那样,重复的dict值从列表中删除或过滤掉,并且仅该dict实例的第一个条目被带入已过滤的输出中。

如果两个键的值相同,则需要删除重复项。

在Python中使用字典/列表理解是否有一种简便的方法?还有另一种更快的方法可以实现这一目标吗?

5 个答案:

答案 0 :(得分:3)

您可以使用key来使用itertools.groupby (x["first"].lower, x["last"].lower())进行分组,然后仅分组分组值的第0个元素:

from itertools import groupby
# https://docs.python.org/3/library/itertools.html#itertools.groupby

my_dict = [
        {'first': 'James', 'middle': 'Smith', 'last': 'Joule'}, 
        {'first': 'James', 'middle': 'smith', 'last': 'joule'},
        {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'},
        {'first': 'Robert', 'middle': 'Edward', 'last': 'Antonio'},
        {'first': 'Robert', 'middle': 'edward', 'last': 'antonio'},
        {'first': 'Robert', 'middle': 'edwrd', 'last': 'Antonio'},
        {'first': 'James', 'middle': 'Jackson', 'last': 'harden'}, 
        {'first': 'James', 'middle': 'jackson', 'last': 'Harden'},
      ]

keys = ["first","last"]

k = [list(data)[0] for key,data in groupby(my_dict, 
                                           key=lambda x: tuple(x[i].lower() for i in keys))]

print(k) 

输出:

[{'first': 'James', 'middle': 'Smith', 'last': 'Joule'}, 
 {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'}, 
 {'first': 'Robert', 'middle': 'Edward', 'last': 'Antonio'}, 
 {'first': 'James', 'middle': 'Jackson', 'last': 'harden'}]

注意事项:

Groupby仅适用于连续键-如果列表末尾有第三个{'first': 'James', 'middle': 'Smith', 'last': 'JOUle'},他会得到它自己的条目:

  

制作一个迭代器,该迭代器从 iterable
返回连续键和组   (来自doku,上方链接)

如果您希望将它们全部归入同一组,则需要先对列表进行分组,然后再对其进行排序。

答案 1 :(得分:2)

首先,将其命名为my_list,而不是my_dict

my_list = [
    {'first': 'James', 'middle': 'Smith', 'last': 'Joule'},
    {'first': 'James', 'middle': 'smith', 'last': 'joule'},
    {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'},
    {'first': 'Robert', 'middle': 'Edward', 'last': 'Antonio'},
    {'first': 'Robert', 'middle': 'edward', 'last': 'antonio'},
    {'first': 'Robert', 'middle': 'edwrd', 'last': 'Antonio'},
    {'first': 'James', 'middle': 'Jackson', 'last': 'harden'},
    {'first': 'James', 'middle': 'jackson', 'last': 'Harden'}
]
keys = ["first", "last"]

然后,您可以通过以下理解实现您的目标:

import collections
temp = collections.OrderedDict([
    (
        tuple(e[k].lower() for k in keys),    # only some keys will determine duplicates
        e,
    )
    for e in my_list])

my_new_list = list(temp.values())

通过按姓氏和姓氏对元​​素进行分组,将排除重复项。以后,如果需要,只需要将其再次投射到列表中即可。

使用OrderedDict可以保留原始顺序。

我还使用.lower()查找不区分大小写的重复项。

答案 2 :(得分:1)

以下解决方案不需要任何import语句,并且可以区分大小写。它还仅考虑键列表中提供的字段,并且在匹配时忽略所有其他字段(the solution provided by Mstaino会在匹配时将所有字段都考虑在内,无论您的键列表中可能包含什么)。

my_dict = [
        {'first': 'James', 'middle': 'Smith', 'last': 'Joule'}, 
        {'first': 'James', 'middle': 'smith', 'last': 'joule'},
        {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'},
        {'first': 'Robert', 'middle': 'Edward', 'last': 'Antonio'},
        {'first': 'Robert', 'middle': 'edward', 'last': 'antonio'},
        {'first': 'Robert', 'middle': 'edwrd', 'last': 'Antonio'},
        {'first': 'James', 'middle': 'Jackson', 'last': 'harden'}, 
        {'first': 'James', 'middle': 'jackson', 'last': 'Harden'},
      ]
keys = ["first","last"]
fields = [''.join([x.lower() for x in \
                   list(map(lambda x : my_dict[i].__getitem__(x), keys))]) \
          for i,v in enumerate(my_dict)]
filtered_dict = [my_dict[i] for i,v in enumerate(fields) if fields.index(v) == i]

如果只想消除连续的重复(如the solution provided by Patrick Artner中的重复),则必须以以下方式声明filtered_dict

filtered_dict = [ my_dict[i] for i,v in enumerate(fields) if i == 0 or v != fields[i-1] ]

答案 3 :(得分:0)

一种解决方案是使用如下所示的pandas数据框。这样可以非常像CSV文件一样删除重复的行。但是,这没有考虑区分大小写,如果需要区分大小写的重复删除,那将是另一种方法。但这工作得很好。

import pandas as pd

my_dict = [
    {'first': 'James', 'middle': 'Smith', 'last': 'Joule'},
    {'first': 'James', 'middle': 'smith', 'last': 'joule'},
    {'first': 'Christian', 'middle': 'Edward', 'last': 'Doppler'},
    {'first': 'Robert', 'middle': 'Edward', 'last': 'Antonio'},
    {'first': 'Robert', 'middle': 'edward', 'last': 'antonio'},
    {'first': 'Robert', 'middle': 'edwrd', 'last': 'Antonio'},
    {'first': 'James', 'middle': 'Jackson', 'last': 'harden'},
    {'first': 'James', 'middle': 'jackson', 'last': 'Harden'}
]


keys = ["first", "last"]

df = pd.DataFrame(my_dict)

df = df.drop_duplicates(keep="first")
print(df)

答案 4 :(得分:0)

首先,请确定您要过滤不区分大小写的邮件。

用于过滤上下限的python解决方案:

values = list(map(lambda x: set(i.lower() for i in x.values()), my_dict))
my_filter_list = [my_dict[i] for i,x in enumerate(values) if values.index(x)==i]