2016-05-13 2 views
0

У меня есть список dicts, как это (может иметь до 12000 записей, хотя):Получить только первые дубликаты в списке dicts с питоном

[ 
{'date': datetime.datetime(2016, 1, 31, 0, 0), 'title': 'Entry'}, 
{'date': datetime.datetime(2016, 1, 11, 0, 0), 'title': 'Something'}, 
{'date': datetime.datetime(2016, 1, 01, 0, 0), 'title': 'Entry'} 
] 

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

+2

почему список dicts? Почему не один большой словарь с названием как ключи и даты как значения? то он по сути не мог иметь дубликатов. –

+0

Я раньше не использовал python и должен очищать данные с веб-сайта. Я просто взял один подход со списком диктонов случайно. Поэтому никаких конкретных причин для меня – Sannin

ответ

1

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

import datetime 

dict_list = [ 
    {'date': datetime.datetime(2016, 1, 31, 0, 0), 'title': 'Entry'}, 
    {'date': datetime.datetime(2016, 1, 11, 0, 0), 'title': 'Something'}, 
    {'date': datetime.datetime(2016, 1, 01, 0, 0), 'title': 'Entry'} 
] 

dict_keys = set(map(lambda x: x["title"], dict_list)) 

earliest_entries = {k:min(x["date"] for x in dict_list if x["title"] == k) for k in dict_keys} 

Выход:

>>> earliest_entries 
{'Entry': datetime.datetime(2016, 1, 1, 0, 0), 'Something': datetime.datetime(2016, 1, 11, 0, 0)} 
>>> 
2

Если вы хотите сохранить список в формате он находится в то вы можете просто держать set из seen уникальных названий и идти по списку либо удаление записей или добавление к seen:

def r_enumerate(iterable): 
    #use itertools.izip and xrange if you are using python 2! 
    return zip(reversed(range(len(iterable))), 
       reversed(iterable)) 

seen = set() 
for i, subdata in r_enumerate(data): 
    if subdata['title'] in seen: 
     del data[i] 
    else: 
     seen.add(subdata['title']) 

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


С другой стороны, если вы готовы использовать словарь для хранения всех записей вместо списка маленьких словарей это действительно очень просто:

{partdict['title']: partdict['date'] for partdict in LIST_OF_DICTS} 

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

Чтобы вернуться к формату списка (но содержат только самую старую запись каждого имени) вы можете сделать что-то вроде:

[{'title':title, 'date':date} for title,date in DICT_FORM] 

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

+0

Благодарим за помощь. Я уже использовал решение jDo, потому что это было проще всего в моем коде. Порядок данных для меня не важен. Я просто подумал, что было бы легче, если известно, что последний (или первый с перевернутым списком) заголовок - тот, который нужно сохранить. Список уже отсортирован, когда я получаю данные. – Sannin

+0

если вы использовали ответ jDo, почему вы его не приняли? –

+0

Я забыл. Спасибо за напоминание. – Sannin

Смежные вопросы