使用最大条件比较和删除列表列表中的列表

时间:2018-05-03 10:53:03

标签: python python-3.x python-2.7 list sorting

我有一个像这样的列表列表:

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 :(得分:2)

这可以通过itertools.groupbysorted的组合实现。

以下解决方案明确使用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']]

答案 1 :(得分:2)

我将在不使用任何库的情况下提供解决方案。

首先,您需要按最后一个字段对项目进行分组。

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']]

答案 2 :(得分:2)

这是使用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']]

答案 3 :(得分:2)

作为从内存使用和运行时角度出发的优化方式,您可以遍历子列表并跟踪那些具有更长日期的子列表。并且由于您希望对具有重复最后一项的列表执行此操作,因此将最后一项作为键的字典是您可以使用的最佳数据结构。

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']]

答案 4 :(得分:0)

我最终得到了与@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()])