Python-根据字典值从字典列表中删除重复项

时间:2019-08-05 11:20:48

标签: python dictionary

我有一个字典列表,其中包含一些重复的ID,我想将具有值的字典保留在rsrp下,并删除那些具有0的字典,但是如果存在重复的字典,并且两次的rsrp为0我需要保留它。

下面是当前和所需的列表示例,有没有简单的方法可以做到这一点?通过循环查找非“ 0”很容易,但是如果匹配的ID为“ 0”,则不确定

current_list = [
    {'id': 255, 'rssi': -108.0},
    {'id': 255, 'rssi': '0'},
    {'id': 301, 'rssi': -82.0},
    {'id': 301, 'rssi': '0'},
    {'id': 263, 'rssi': -85.0},
    {'id': 263, 'rssi': '0'},
    {'id': 18, 'rssi': '0'},
    {'id': 18, 'rssi': '0'}
]

desired_list = [
    {'id': 255, 'rssi': -108.0},
    {'id': 301, 'rssi': -82.0},
    {'id': 263, 'rssi': -85.0},
    {'id': 18, 'rssi': '0'}
]

5 个答案:

答案 0 :(得分:3)

itertools recipes中有一种称为unique_everseen的方法:

from itertools import filterfalse

def unique_everseen(iterable, key=None):
    "List unique elements, preserving order. Remember all elements ever seen."
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
    # unique_everseen('ABBCcAD', str.lower) --> A B C D
    seen = set()
    seen_add = seen.add
    if key is None:
        for element in filterfalse(seen.__contains__, iterable):
            seen_add(element)
            yield element
    else:
        for element in iterable:
            k = key(element)
            if k not in seen:
                seen_add(k)
                yield element

您可以使用它来获取所需的列表:

desired_list = list(unique_everseen(current_list, key=lambda x: x["rssi"]))
# [{'id': 255, 'rssi': -108.0}, {'id': 255, 'rssi': '0'}, 
#  {'id': 301, 'rssi': -82.0}, {'id': 263, 'rssi': -85.0}]

剩下要做的就是使用'rssi'的{​​{1}}参数选择key

答案 1 :(得分:2)

使用简单的迭代。

例如:

current_list = [
    {'id': 255, 'rssi': -108.0},
    {'id': 255, 'rssi': '0'},
    {'id': 301, 'rssi': -82.0},
    {'id': 301, 'rssi': '0'},
    {'id': 263, 'rssi': -85.0},
    {'id': 263, 'rssi': '0'},
    {'id': 18, 'rssi': '0'},
    {'id': 18, 'rssi': '0'}
]
seen = set()
result = []
for i in sorted(current_list, key=lambda x: True if x["rssi"] == "0" else False):
    if (i["id"] not in seen and i["rssi"] != "0") or \
            (i["id"] not in seen and i["rssi"] == "0"):
        result.append(i)
        seen.add(i["id"])

输出:

[{'id': 255, 'rssi': -108.0},
 {'id': 301, 'rssi': -82.0},
 {'id': 263, 'rssi': -85.0},
 {'id': 18, 'rssi': '0'}]

答案 2 :(得分:0)

如果您可以在项目中使用外部库,则可以利用Pandas向量化操作。

例如:

import pandas as pd

df = pd.DataFrame(current_list)
df["rssi"] = pd.to_numeric(df["rssi"])
df = df[(df["rssi"] != 0) | (df.groupby("id").transform("min") == 0)["rssi"]]
df = df.drop_duplicates()
df.to_dict("records")

答案 3 :(得分:0)

使用itertools.groupby的一种解决方案。如果只有rssi0项,我们保留一个。我们将所有其他非零rssi项添加到输出列表:

current_list = [
    {'id': 255, 'rssi': -108.0},
    {'id': 255, 'rssi': '0'},
    {'id': 301, 'rssi': -82.0},
    {'id': 301, 'rssi': '0'},
    {'id': 263, 'rssi': -85.0},
    {'id': 263, 'rssi': '0'},
    {'id': 18, 'rssi': '0'},
    {'id': 18, 'rssi': '0'}
]

from itertools import groupby

out = []
for v, g in groupby(sorted(current_list, key=lambda k: (k['id'], k['rssi'] == '0')), lambda k: k['id']):
    out.append(next(g)) # ensure we add at least one `0`
    out.extend(i for i in g if i['rssi'] != '0')  # add any non-zero `rssi` items


from pprint import pprint
pprint(out)

打印:

[{'id': 18, 'rssi': '0'},
 {'id': 255, 'rssi': -108.0},
 {'id': 263, 'rssi': -85.0},
 {'id': 301, 'rssi': -82.0}]

答案 4 :(得分:0)

如果不使用任何import,我将按照以下方式进行操作:

current_list = [
    {'id': 255, 'rssi': -108.0},
    {'id': 255, 'rssi': '0'},
    {'id': 301, 'rssi': -82.0},
    {'id': 301, 'rssi': '0'},
    {'id': 263, 'rssi': -85.0},
    {'id': 263, 'rssi': '0'},
    {'id': 18, 'rssi': '0'},
    {'id': 18, 'rssi': '0'}
]
output = {}
for i in current_list:
    if not i['id'] in output:
        output[i['id']] = []
    output[i['id']].append(i['rssi'])
# now output is {255: [-108.0, '0'], 301: [-82.0, '0'], 263: [-85.0, '0'], 18: ['0', '0']}
def func(x):
    for j in x:
        if j!='0':
            return j
    return '0'
desired_list = [{'id':i[0],'rssi':func(i[1])} for i in output.items()]
print(desired_list)

输出:

[{'id': 255, 'rssi': -108.0}, {'id': 301, 'rssi': -82.0}, {'id': 263, 'rssi': -85.0}, {'id': 18, 'rssi': '0'}]