小能豆

如何对列表列表进行排序并仅保留每个第一个元素的最大第二个元素?

py

假设我有一些列表:

lst = [[2,6],[1,4],[0,1],[1,1],[2,3],[0,2]]

我想按第一个元素对lst进行排序,并对于每个子列表,按第一个元素分组时保留具有最大第二个元素的子列表。

因此结果将是:

results
>>> [[0,2],[1,4],[2,6]]

有人能帮助我吗?


阅读 36

收藏
2024-11-17

共2个答案

小能豆

可以使用 Python 的 itertools.groupbymax 来实现您的需求。以下是完整的实现步骤:


实现步骤:

  1. 按第一个元素对列表排序,这样 groupby 能正确分组。
  2. 使用 groupby 根据第一个元素分组。
  3. 对每个分组,选择第二个元素最大的子列表。

代码实现:

from itertools import groupby

lst = [[2,6], [1,4], [0,1], [1,1], [2,3], [0,2]]

# 第一步:按第一个元素排序
sorted_lst = sorted(lst, key=lambda x: x[0])

# 第二步和第三步:分组并选择每组中第二个元素最大的子列表
results = [
    max(group, key=lambda x: x[1])  # 找到每组中第二个元素最大的子列表
    for _, group in groupby(sorted_lst, key=lambda x: x[0])
]

print(results)

输出结果:

[[0, 2], [1, 4], [2, 6]]

代码详解:

  1. 排序:
    python sorted_lst = sorted(lst, key=lambda x: x[0])
    这样排序后列表变为:
    py [[0, 1], [0, 2], [1, 4], [1, 1], [2, 6], [2, 3]]

  2. 分组:
    python groupby(sorted_lst, key=lambda x: x[0])
    groupby 会按第一个元素分组,例如:

  3. 0: [[0, 1], [0, 2]]
  4. 1: [[1, 4], [1, 1]]
  5. 2: [[2, 6], [2, 3]]

  6. 找最大值:
    python max(group, key=lambda x: x[1])
    对每个分组,找到第二个元素最大的子列表。例如:

  7. 0: [[0, 2]]
  8. 1: [[1, 4]]
  9. 2: [[2, 6]]

简化版代码:

如果喜欢简洁代码,可以用一行完成:

from itertools import groupby
results = [
    max(group, key=lambda x: x[1])
    for _, group in groupby(sorted(lst, key=lambda x: x[0]), key=lambda x: x[0])
]
print(results)

这种方法高效且简洁,非常适合解决您的问题。

2024-11-17
小能豆

您可以使用以下方法进行操作np.maximum.reduceat

import numpy as np
lst = np.array([[2,6],[1,4],[0,1],[1,1],[2,3],[0,2]])
lst = lst[np.argsort(lst[:,0])] #sorting lst by first row
u, idx = np.unique(lst[:,0], return_index = True) 
print(np.c_[u, np.maximum.reduceat(lst[:,1], idx)])

首先对数组进行排序。然后需要获取将数组拆分为组的索引:idx = [0, 2, 4]以及第一列的相应值u = [0, 1, 2]。最后,使用np.maximum.reduceat以获取从idx指定索引开始的组的最大值,并将其连接到右侧显示u

备注:numpy在这里使用了一个广泛使用的库,它允许将循环推入 C 级别,速度要快得多。纯 Python 解决方案也值得关注。

奖励:这实际上是一个使用numpy_indexed专用于数组 groupby 操作的库(不太广泛使用)的单行代码:

import numpy_indexed as npi
import numpy as np
np.transpose(npi.group_by(lst[:, 0]).max(lst[:, 1]))
2024-11-17