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

Примечания: обновляется только длина, категория остается статичной. Я знаю, какое из них является последним обновлением, потому что для этого объекта у него будет самая последняя отметка времени

Данные поступают так:

[{u'length': u'1',
  u'category': u'3',
  u'entity': u'entityA',
  u'timestamp': u'1562422690'},
 {u'length': u'1.1',
  u'category': u'3',
  u'entity': u'entityA',
  u'timestamp': u'1562422691'},
 {u'length': u'1.2',
  u'category': u'3',
  u'entity': u'entityA',
  u'timestamp': u'1562422692'},
 {u'length': u'0.9',
  u'category': u'3',
  u'entity': u'entityB',
  u'timestamp': u'1562422689'},
 {u'length': u'0.9',
  u'category': u'3',
  u'entity': u'entityB',
  u'timestamp': u'1562422690'}]

Мне нужно манипулировать этим, чтобы я получил только:

{u'entityA':{u'length': u'1.2', 
             u'category': u'3', 
             u'entity': u'entityA', 
             u'timestamp': u'1562422692'},
 u'entityB':{u'length': u'0.9', 
             u'category': u'3', 
             u'entity': u'entityB', 
             u'timestamp': u'1562422690'}}

Я новичок в Python - я знал, что могу достичь этого в SQL с:

select * from
(select
   length, 
   category, 
   entity, 
   timestamp, 
   row_number () over (partition by entity order by timestamp desc) as rnumb
from data
)foo
where rnumb = 1

Но я делаю это в Python, и это кажется слишком большой обходной путь, чтобы пройти через SQL в Python, к сожалению, мой исходный SQL данных не поддерживает row_number ()

Обновление этого вопроса после того, как я попробовал подходы Гиллеспи и Александра. Подход Гиллеспи, похоже, не работает, Александр работает, но становится очень медленным при работе с большим количеством данных - есть ли более быстрая альтернатива?

test_data = [
{u'length': u'0',
  u'category': u'3',
  u'entity': u'entityA',
  u'timestamp': u'1562422690'},
{u'length': u'1',
  u'category': u'3',
  u'entity': u'entityA',
  u'timestamp': u'1562422680'},
{u'length': u'2',
  u'category': u'3',
  u'entity': u'entityB',
  u'timestamp': u'1562422691'},
{u'length': u'3',
  u'category': u'3',
  u'entity': u'entityB',
  u'timestamp': u'1562422688'},
{u'length': u'4',
  u'category': u'3',
  u'entity': u'entityC',
  u'timestamp': u'1562422630'},
{u'length': u'5',
  u'category': u'3',
  u'entity': u'entityC',
  u'timestamp': u'1562422645'}
]
>>> test_gillespie = max(test_data, lambda x: x["timestamp"])
test_gillespie
[{u'category': u'3',
  u'entity': u'entityA',
  u'length': u'0',
  u'timestamp': u'1562422690'},
 {u'category': u'3',
  u'entity': u'entityA',
  u'length': u'1',
  u'timestamp': u'1562422680'},
 {u'category': u'3',
  u'entity': u'entityB',
  u'length': u'2',
  u'timestamp': u'1562422691'},
 {u'category': u'3',
  u'entity': u'entityB',
  u'length': u'3',
  u'timestamp': u'1562422688'},
 {u'category': u'3',
  u'entity': u'entityC',
  u'length': u'4',
  u'timestamp': u'1562422630'},
 {u'category': u'3',
  u'entity': u'entityC',
  u'length': u'5',
  u'timestamp': u'1562422645'}]
>>>test_alexander = {entity: sorted([d for d in test_data if d.get('entity') == entity], key=lambda x: x['timestamp'])[-1]
     for entity in set(d.get('entity') for d in test_data)}
test_alexander
{u'entityA': {u'category': u'3',
  u'entity': u'entityA',
  u'length': u'0',
  u'timestamp': u'1562422690'},
 u'entityB': {u'category': u'3',
  u'entity': u'entityB',
  u'length': u'2',
  u'timestamp': u'1562422691'},
 u'entityC': {u'category': u'3',
  u'entity': u'entityC',
  u'length': u'5',
  u'timestamp': u'1562422645'}}

2
M V 6 Июл 2019 в 21:00

3 ответа

Лучший ответ

Предполагая, что ваши данные присвоены переменной с именем data, вы можете использовать словарное понимание вместе с sorted. Для каждого объекта (set(d.get('entity') for d in data) создает набор всех уникальных объектов) отсортируйте его данные на основе отметки времени, а затем выберите последний элемент (т. Е. Самый последний) с помощью выбора индекса [-1].

>>> {entity: sorted([d for d in data if d.get('entity') == entity], key=lambda x: x['timestamp'])[-1]
     for entity in set(d.get('entity') for d in data)}
{'entityA': {'length': '1.2',
  'category': '3',
  'entity': 'entityA',
  'timestamp': '1562422692'},
 'entityB': {'length': '0.9',
  'category': '3',
  'entity': 'entityB',
  'timestamp': '1562422690'}}

Более быстрый метод предполагает использование панд.

import pandas as pd

df = pd.DataFrame(data).sort_values('timestamp')
result = df.groupby('entity', as_index=False).last()
>>> result
    entity category length   timestamp
0  entityA        3    1.2  1562422692
1  entityB        3    0.9  1562422690

>>> result.to_dict('r')
[{'entity': 'entityA',
  'category': '3',
  'length': '1.2',
  'timestamp': '1562422692'},
 {'entity': 'entityB',
  'category': '3',
  'length': '0.9',
  'timestamp': '1562422690'}]

JSDoc: указание типа объекта, передаваемого в качестве параметра?

0
Alexander 7 Июл 2019 в 17:25

Я лучше сформулировал свой следующий вопрос о производительности в новом вопросе, если у вас есть похожая проблема, проверьте его: Есть ли более быстрая альтернатива этому подходу, чтобы получить последнее сообщение об обновлении из списка dict?

0
M V 7 Июл 2019 в 15:48

Попробуйте что-то вроде этого:

test_data = [
{u'length': u'0',
  u'category': u'3',
  u'entity': u'entityA',
  u'timestamp': u'1562422690'},
{u'length': u'1',
  u'category': u'3',
  u'entity': u'entityA',
  u'timestamp': u'1562422680'},
{u'length': u'2',
  u'category': u'3',
  u'entity': u'entityB',
  u'timestamp': u'1562422691'},
{u'length': u'3',
  u'category': u'3',
  u'entity': u'entityB',
  u'timestamp': u'1562422688'},
{u'length': u'4',
  u'category': u'3',
  u'entity': u'entityC',
  u'timestamp': u'1562422630'},
{u'length': u'5',
  u'category': u'3',
  u'entity': u'entityC',
  u'timestamp': u'1562422645'}
]

test_gillespie = max(test_data, key=lambda x: int(x["timestamp"]))

print(test_gillespie)

Выход:

{'length': '2', 'category': '3', 'entity': 'entityB', 'timestamp': '1562422691'}

См. https://repl.it/repls/StimulationLightcoralBotany.

0
Gillespie 7 Июл 2019 в 20:26