我有一个像这样的列表列表:
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']]
我有什么想法可以做到这一点吗?
答案 0 :(得分:2)
这可以通过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']]
答案 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()])