Сравнить и удалить списки из списка списков, используя условие max - PullRequest
0 голосов
/ 03 мая 2018

У меня есть список таких списков:

a=[['2012-05-11','yes','44','426.24'],['2013-03-22','no','12','426.24'],['2018-08-13','yes','88','426.24'] ,['2017-05-11','yes','404','450.24']]

Я хочу удалить все списки с одинаковым 4-м значением ( a[0][3],a[1][3] ...) и разрешить только список с самой последней датой, поэтому в моем случае я хочу этот результат:

a=[['2018-08-13','yes','88','426.24'] ,['2017-05-11','yes','404','450.24']]

Есть идеи, как мне это сделать?

Ответы [ 5 ]

0 голосов
/ 03 мая 2018

У меня появилась та же идея, что и у @Kasramvd, но с более простым для понимания кодом (это должно сделать идею более понятной для менее опытных программистов на Python):

from datetime import datetime

def myfilter (arr):
    results = dict()

    for item in arr:
        index = item[3]
        if index not in results or datetime.strptime(item[0], '%Y-%m-%d') > datetime.strptime(results[index][0], '%Y-%m-%d'):
            results[index] = item

    print([item for _, item in results.items()])
0 голосов
/ 03 мая 2018

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

In [2]: from datetime import datetime

In [3]: def filter(arr):
   ...:     _container = {}
   ...:     for dt, *mid, last in arr:
   ...:         date_obj = datetime.strptime(dt, '%Y-%m-%d')
   ...:         try:
   ...:             d = _container[last][0]
   ...:             if date_obj > d:
   ...:                  _container[last] = (date_obj, [dt] + mid)
   ...:         except KeyError:
   ...:             _container[last] = (date_obj, [dt] + mid)
   ...:     return [[*rest, last] for last, (_, rest) in _container.items()]

Демо-версия:

In [5]: filter(a)
Out[5]: [['2018-08-13', 'yes', '88', '426.24'], ['2017-05-11', 'yes', '404', '450.24']]
0 голосов
/ 03 мая 2018

Я предоставлю решение без использования каких-либо библиотек.

Прежде всего, вам нужно сгруппировать элементы по последнему полю.

dict = {}
for elem in a:
   if elem[-1] not in dict:
      dict[elem[-1]] = []
   dict[elem[-1]].append(elem[:-1])

print(dict)

{'426.24': [['2012-05-11', 'yes', '44'], ['2013-03-22', 'no', '12'], ['2018-08-13', 'yes', '88']], '450.24': [['2017-05-11', 'yes', '404']]}

Затем сохраните только последний элемент для каждого ключа в словаре .

for key in dict:
    dict[key] = sorted([elem[0] for elem in dict[key]], key=lambda x: datetime.datetime.strptime(x, '%Y-%m-%d'))
    dict[key] = dict[key].pop()

Тогда просто используйте list comprehension для фильтрации исходного массива.

a = [elem for elem in a if elem[0] == dict[elem[-1]]]

выход

[['2018-08-13', 'yes', '88', '426.24'], ['2017-05-11', 'yes', '404', '450.24']]
0 голосов
/ 03 мая 2018

Это решение, использующее collections.defaultdict. Идея состоит в том, чтобы реструктурировать ваш словарь по ключу. Затем используйте max с пользовательским аргументом key для извлечения требуемого результата.

from collections import defaultdict

d = defaultdict(list)

for *data, key in a:
    d[key].append(data)

res = [max(v, key=lambda x: datetime.strptime(x[0], '%Y-%m-%d'))+[k]
       for k, v in d.items()]

[['2018-08-13', 'yes', '88', '426.24'],
 ['2017-05-11', 'yes', '404', '450.24']]
0 голосов
/ 03 мая 2018

Это возможно с помощью комбинации itertools.groupby и sorted.

В приведенном ниже решении явно используется преобразование datetime для сортировки дат.

После сортировки вам нужно только извлечь последний элемент каждого элемента groupby для требуемой записи.

from datetime import datetime
from itertools import groupby
from operator import itemgetter

sorter = sorted(a, key=lambda x: (x[3], datetime.strptime(x[0], '%Y-%m-%d')))
grouper = groupby(sorter, key=itemgetter(3))

res = [list(j)[-1] for _, j in grouper]

[['2018-08-13', 'yes', '88', '426.24'],
 ['2017-05-11', 'yes', '404', '450.24']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...