2015-05-14 2 views
1

У меня есть структура данных, как это:Как удалить дубликаты записей в вложенном контейнере

[{'remote': '1', 'quantity': 1.0, 'timestamp': 1}, 
{'remote': '2', 'quantity': 1.0, 'timestamp': 2}, 
{'remote': '2', 'quantity': 1.0, 'timestamp': 3}, ...] 

список словарей. Моя задача - найти повторяющиеся записи относительно удаленного значения. Если я нашел записи с тем же удаленным значением, что я хочу удалить все, кроме одного с самым новым значением метки времени.

В этом примере мне пришлось найти и удалить словарь, потому что у третьего есть тот же самый пульт, но более новая отметка времени.

Я не знаком с питоном. Я гугле много, и нашел только решения для списков, как это:

How can I count the occurrences of a list item in Python?

Моя проблема в том, что IAM не достаточно умны, чтобы применить это на мою проблему. Кроме того, решение должно быть несколько эффективным, поскольку оно должно постоянно работать в фоновом режиме с относительно низкой вычислительной мощностью.

Благодарим за помощь!

+0

Может ли вы добавить свой ожидаются из положить и ваш код, который вы пробовали до сих пор? – Kasramvd

+0

являются ключами в каждом dict и являются диктофонами в отсортированном порядке? –

ответ

1

Вход:

entries = [{'remote': '1', 'quantity': 1.0, 'timestamp': 1}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 2}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 3}] 

Удаление:

newest = {} 
for entry in entries: 
    current = newest.get(entry['remote']) 
    if current is None or entry['timestamp'] > current['timestamp']: 
     newest[entry['remote']] = entry 
entries[:] = newest.values() 

Выход:

from pprint import pprint 
pprint(entries) 

Prints: 
[{'quantity': 1.0, 'remote': '2', 'timestamp': 3}, 
{'quantity': 1.0, 'remote': '1', 'timestamp': 1}] 
+0

Хорошо работает. Спасибо! – user3394244

1

Если у вас есть это:

data = [{"remote":1, "quantity":1.0, "timestamp":1}, 
     {"remote":2, "quantity":1.0, "timestamp":2}, 
     {"remote":2, "quantity":1.0, "timestamp":3}] 

Вы можете отфильтровать записи так:

filtered_data = [] 
for d1 in sorted(data, key=lambda e: e["timestamp"], reverse=True): 
    for d2 in filtered_data: 
     if d1["remote"] == d2["remote"]: 
      break 
    else: 
     filtered_data.append(d1) 
+0

Ваш код не работает должным образом. См. Https://ideone.com/kHGvFn – Alik

+0

Теперь он работает, но я думаю, что решение Стефана Почмана намного эффективнее, чем мое – BurningKarl

+0

, а затем: – Alik

1

Если dicts будут в отсортированном порядке на основе ключа 'remote', вы можете сгруппировать их с помощью ключа 'remote' и получить последнюю запись, которая будет последняя метка времени.

l = [{'remote': '1', 'quantity': 1.0, 'timestamp': 1}, 
{'remote': '2', 'quantity': 1.0, 'timestamp': 2}, 
{'remote': '2', 'quantity': 1.0, 'timestamp': 3}] 


from itertools import groupby 
from operator import itemgetter 

l[:] = (list(v)[-1] for _, v in groupby(l,key=(itemgetter("remote")))) 

print(l) 
[{'timestamp': 1, 'remote': '1', 'quantity': 1.0}, 
{'timestamp': 3, 'remote': '2', 'quantity': 1.0}] 

l[:] изменяет первоначальный список, (list(v)[-1] for k,v in groupby(l,key=(itemgetter("remote")))) это выражение генератор, который означает, что мы не должны хранить все содержимое памяти сразу которое, если память также вопрос поможет.

Это также будет работать для неупорядоченных данных после того, как обманутые всегда вместе и последняя боян приходит последним:

l = [{'remote': '1', 'quantity': 1.0, 'timestamp': 1}, 
      {'remote': '4', 'quantity': 1.0, 'timestamp': 1}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 2}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 3}] 

l[:] = (list(v)[-1] for k,v in groupby(l, key=(itemgetter("remote")))) 

print(l) 
[{'timestamp': 1, 'remote': '1', 'quantity': 1.0}, {'timestamp': 1, 'remote': '4', 'quantity': 1.0}, {'timestamp': 3, 'remote': '2', 'quantity': 1.0}] 

Или, если обманутые не отсортирован получить максимально на основе временной метки:

l = [{'remote': '1', 'quantity': 1.0, 'timestamp': 1}, 
      {'remote': '4', 'quantity': 1.0, 'timestamp': 1}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 3}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 2}] 

l[:] = (max(v,key=itemgetter("timestamp")) for _, v in groupby(l, key=(itemgetter("remote"))) 


[{'timestamp': 1, 'remote': '1', 'quantity': 1.0}, {'timestamp': 1, 'remote': '4', 'quantity': 1.0}, {'timestamp': 3, 'remote': '2', 'quantity': 1.0}] 

Если вы собираетесь сортировать, вы должны сделать обратную сортировку на месте с помощью ключа дистанционного управления, после чего они будут звонить по следующей группе: v, чтобы получить последние:

l = [{'remote': '1', 'quantity': 1.0, 'timestamp': 1}, 
      {'remote': '4', 'quantity': 1.0, 'timestamp': 1}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 3}, 
      {'remote': '2', 'quantity': 1.0, 'timestamp': 2}] 

l.sort(key=itemgetter("remote"),reverse=True) 
l[:] = (next(v) for _, v in groupby(l, key=(itemgetter("remote")))) 

print(l) 

Сортировка изменяет порядок диктонов, хотя это может оказаться неприемлемым для вашей проблемы, если ваш dicts соответствует вашему вводу, тогда вам не нужно беспокоиться о сортировке в любом случае.

+0

@JoseRicardoBustosM. Я, хотя оба ключа должны были совпадать, чтобы считаться обманом, но это всего лишь удаленный ключ. –

+1

да, я понимаю сейчас ... спасибо –

+0

@JoseRicardoBustosM. не беспокойся. –

0
In [55]: from itertools import groupby 

In [56]: from operator import itemgetter 


In [58]: a 
Out[58]: 
[{'quantity': 1.0, 'remote': '1', 'timestamp': 1}, 
{'quantity': 1.0, 'remote': '2', 'timestamp': 2}, 
{'quantity': 1.0, 'remote': '2', 'timestamp': 3}] 

Сортировано базируемый на метку времени и так как вам нужен самый последний (максимум), обратная правда

In [58]: s_a=sorted(a,key=lambda x: x['timestamp'],reverse = True) 
In [59]: groups=[] 
In [60]:for k,g in groupby(s_a,key=lambda x:x['remote']): 
    groups.append(list(g)) 
In [69]: [elem[0] for elem in groups] 
Out[69]: 
[{'quantity': 1.0, 'remote': '2', 'timestamp': 3}, 
{'quantity': 1.0, 'remote': '1', 'timestamp': 1}] 
Смежные вопросы