列表列表 - 比较相邻值,如果第二个元素相同 - 取旧的

List of lists - Compare neighboring values and IF second elements are the same - take older one

我正在尝试为这个任务找到一个更优雅的解决方案:我们有一个包含日期和值对的列表列表 -> 需要与邻居值进行比较并且如果值相同 - 我们只选择最早的日期(但它只适用于近邻)。

l = [[datetime.datetime(2021, 1, 1, 0, 0), 0],
    [datetime.datetime(2021, 3, 1, 0, 0), 0],  # need to skipp
    [datetime.datetime(2021, 4, 1, 0, 0), 2],
    [datetime.datetime(2021, 8, 1, 0, 0), 0],  # keep!
    [datetime.datetime(2021, 10, 1, 0, 0), 5]]

预期结果:

[datetime.datetime(2021, 1, 1, 0, 0),
 datetime.datetime(2021, 4, 1, 0, 0),
 datetime.datetime(2021, 8, 1, 0, 0),
 datetime.datetime(2021, 10, 1, 0, 0)]

请看一个例​​子,看看我是如何解决这个问题的。非常感谢任何关于如何优化它的想法!

def get_dates_1():  # solution 1 with reverse
    l = [[datetime.datetime(2021, 1, 1, 0, 0), 0],
         [datetime.datetime(2021, 3, 1, 0, 0), 0],   # need to skip
         [datetime.datetime(2021, 4, 1, 0, 0), 2],
         [datetime.datetime(2021, 8, 1, 0, 0), 5],
         [datetime.datetime(2021, 10, 1, 0, 0), 5]]  # need to skip

    l.reverse()
    dates = []

    for i in range(len(l)):
        if i < len(l) - 1:
            if l[i][1] != l[i + 1][1]:
                dates.append(l[i][0])
        else:
            dates.append(l[i][0])
    return list(reversed(dates))

def get_dates_2():   # solution 2 w/o reverse
    l = [[datetime.datetime(2021, 1, 1, 0, 0), 0],
         [datetime.datetime(2021, 3, 1, 0, 0), 0],   # need to skip
         [datetime.datetime(2021, 4, 1, 0, 0), 2],
         [datetime.datetime(2021, 8, 1, 0, 0), 5],
         [datetime.datetime(2021, 10, 1, 0, 0), 5]]  # need to skip

    l.sort(key=lambda x: x[0])
    result = [l[0]]
    for date, value in l:
        if value != result[-1][1]:
            result.append([date, value])

    dates = [x for x, _ in result]
    return dates

预计:

[datetime.datetime(2021, 1, 1, 0, 0),
 datetime.datetime(2021, 4, 1, 0, 0),
 datetime.datetime(2021, 8, 1, 0, 0)]

我的解决方案使用 itertools.groupyby 将列表分成子组。

import datetime
import itertools


def get_dates():

    my_list = [
        [datetime.datetime(2021, 3, 1, 0, 0), 0],
        [datetime.datetime(2021, 1, 1, 0, 0), 0],

        [datetime.datetime(2021, 4, 1, 0, 0), 2],

        [datetime.datetime(2021, 8, 1, 0, 0), 5],
        [datetime.datetime(2021, 10, 1, 0, 0), 5]
    ]

    result = [
        # Within each group, sort, and pick out the first (oldest) list
        sorted(group)[0][0]

        # Group the sub-lists by the second element
        for _, group in itertools.groupby(my_list, key=lambda li: li[1])
    ]

    return result


for x in get_dates():
    print(x)

输出:

[datetime.datetime(2021, 1, 1, 0, 0), 0]
[datetime.datetime(2021, 4, 1, 0, 0), 2]
[datetime.datetime(2021, 8, 1, 0, 0), 5]