从列表Python中排序和删除

时间:2017-08-03 05:13:33

标签: python list sorting dictionary

我有一个dict列表,列表中的每个dict都有一个字符串格式的时间戳和一个键。特定键可以在列表中重复多次。我想只保留带有最新时间戳的密钥的dict,并从列表中删除/删除所有其他的dicts。我实现解决方案的一种方法是使用另一个变量并循环遍历所有键并与现有键进行比较。

有没有更好的方法使用列表理解或itertools或任何其他方式解决此问题

以下是输入数据示例

data = [
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:21.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:22.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:23.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:19.762278'},
    {'key': 'key3', 'timestamp': '2017-08-03T10:24:25.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:11.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:45.762278'},
    {'key': 'key4', 'timestamp': '2017-08-03T10:24:39.762278'}
]

这是预期的输出

data = [
    {'key': 'key3', 'timestamp': '2017-08-03T10:24:25.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:22.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:45.762278'},
    {'key': 'key4', 'timestamp': '2017-08-03T10:24:39.762278'}
]

我在python中的实现如下

from dateutil.parser import parse
def sort_and_eliminate(data):
    processed_data = {}
    for cur_item in data:
        key = cur_item.get('key')
        if key not in processed_data:
            processed_data[key] = cur_item
        else:
            ex_item = processed_data.get(key)
            ex_ts = parse(ex_item.get("timestamp"))
            cur_ts = parse(cur_item.get("timestamp"))
            if cur_ts > ex_ts:
                processed_data[key] = cur_item
    return processed_data.values()

有没有更好的方法使用列表理解或itertools或任何其他方式解决此问题

5 个答案:

答案 0 :(得分:1)

这是一种方法。

根据键和时间戳对字典进行排序。

x=sorted(data, key=lambda k: (k['key'],k['timestamp']), reverse=True)
print(x)

[{'key': 'key4', 'timestamp': '2017-08-03T10:24:39.762278'}, 
 {'key': 'key3', 'timestamp': '2017-08-03T10:24:25.762278'}, 
 {'key': 'key2', 'timestamp': '2017-08-03T10:24:22.762278'}, 
 {'key': 'key2', 'timestamp': '2017-08-03T10:24:19.762278'}, 
 {'key': 'key2', 'timestamp': '2017-08-03T10:24:11.762278'}, 
 {'key': 'key1', 'timestamp': '2017-08-03T10:24:45.762278'},  
 {'key': 'key1', 'timestamp': '2017-08-03T10:24:23.762278'}, 
 {'key': 'key1', 'timestamp': '2017-08-03T10:24:21.762278'}]

创建新列表并仅插入第一次出现的密钥

new_list=[]
temp=None
for values in x:
  if values['key']!=temp:
    new_list.append(values)
    temp=values['key']
print(new_list)

[{'key': 'key4', 'timestamp': '2017-08-03T10:24:39.762278'}, 
 {'key': 'key3', 'timestamp': '2017-08-03T10:24:25.762278'}, 
 {'key': 'key2', 'timestamp': '2017-08-03T10:24:22.762278'}, 
 {'key': 'key1', 'timestamp': '2017-08-03T10:24:45.762278'}]

希望这有帮助!

答案 1 :(得分:0)

from datetime import datetime
from operator import itemgetter
from itertools import groupby
from dateutil.parser import parse

expected = [
    {'key': 'key3', 'timestamp': '2017-08-03T10:24:25.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:22.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:45.762278'},
    {'key': 'key4', 'timestamp': '2017-08-03T10:24:39.762278'}
]

data = [
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:21.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:22.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:23.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:19.762278'},
    {'key': 'key3', 'timestamp': '2017-08-03T10:24:25.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:11.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:45.762278'},
    {'key': 'key4', 'timestamp': '2017-08-03T10:24:39.762278'}
]


# alt way without dateutil
def dtconv(s):
    return datetime.strptime(s, "%Y-%m-%dT%H:%M:%S.%f")

ds = sorted(data, key=lambda x: (x['key'], parse(x['timestamp'])), reverse=True)

result = []
for grouper, group in groupby(ds, key=itemgetter('key')):
    result.append(next(group))

print("result:")
for r in result:
    print(r)

print("expected")
for e in expected:
    print(e)

# demonstrate it's equal to expected value
print(sorted(result, key=itemgetter('key')) == sorted(expected, key=itemgetter('key')))

尝试按键和日期戳排序列表。然后你可以做groupby并取第一个元素,这就是你想要保留的东西。

答案 2 :(得分:0)

from dateutil.parser import parse

data = [
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:21.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:22.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:23.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:19.762278'},
    {'key': 'key3', 'timestamp': '2017-08-03T10:24:25.762278'},
    {'key': 'key2', 'timestamp': '2017-08-03T10:24:11.762278'},
    {'key': 'key1', 'timestamp': '2017-08-03T10:24:45.762278'},
    {'key': 'key4', 'timestamp': '2017-08-03T10:24:39.762278'}]


all_keys = [k['key'] for k in data]

all_keys_unique = set(all_keys)

new_dict = {}

for k in all_keys_unique:

    #find all values for that key and parse them
    values_of_key = [j['timestamp'] for j in data if k == j['key']]

    parsed_values = [parse(k2) for k2 in values_of_key]

    #use max to find latest time step, works on datetimes
    #and add to dictionary
    new_dict[k] = max(parsed_values)

print(new_dict)

答案 3 :(得分:0)

按时间戳字符串的相反顺序对数据进行排序,然后每个唯一键的第一个外观将是您要保留的那个。

ctx.channel().close().sync()

答案 4 :(得分:0)

只需创建另一个以键值为键的dict,并比较时间戳并将最新时间戳作为值插入。