过滤列表中的两个第一个匹配元素

问题描述 投票:4回答:2

我有一个按升序排序的列表列表,类似于这个:

input = [[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[3,1],[6,1],[6,2]]

我想过滤此列表,以便新列表只包含位置0中匹配整数的前两个(或唯一)元素,如下所示:

output = [[1,1],[1,2],[2,1],[2,2],[3,1],[6,1],[6,2]]

如果剩余元素(不符合标准的元素)将保留在输入列表中,而匹配元素将单独存储,那将是理想的。

我该怎么做呢?

先感谢您!

编辑:索引1上的元素实际上可以是任何整数,例如[[1,6],[1,7],[1,8],[2,1],[2,2]]

python python-3.x list filter iteration
2个回答
6
投票

Pandas

虽然这有点矫枉过正,但我​​们可以使用pandas:

import pandas as pd

pd.DataFrame(d).groupby(0).head(2).values.tolist()

d原始列表。然后产生:

>>> pd.DataFrame(d).groupby(0).head(2).values.tolist()
[[1, 1], [1, 2], [2, 1], [2, 2], [3, 1], [6, 1], [6, 2]]

请注意,这将返回列表的副本,而不是原始列表。此外,所有行应具有相同数量的项目。

Itertools groupby and islice

如果按字典顺序排列列表,那么我们可以使用itertools.groupby

from operator import itemgetter
from itertools import groupby, islice

[e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2)]

这再次产生:

>>> [e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2)]
[[1, 1], [1, 2], [2, 1], [2, 2], [3, 1], [6, 1], [6, 2]]

由于我们将引用复制到列表中,因此它也更灵活,并且所有列表可以具有不同数量的元素(这里至少有一个)。

编辑

通过让islice以相反的方式工作,可以获得其余的值:保留除了第一个之外的所有内容:

[e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2, None)]

然后我们获得:

>>> [e for _, g in groupby(d, itemgetter(0)) for e in islice(g, 2, None)]
[[1, 3], [1, 4], [2, 3]]

2
投票

您还可以使用collections.defaultdict按第一个索引对子列表进行分组:

from collections import defaultdict
from pprint import pprint

input_lst = [[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[3,1],[6,1],[6,2]]

groups = defaultdict(list)
for lst in input_lst:
    key = lst[0]
    groups[key].append(lst)

pprint(groups)

这给了这个分组字典:

defaultdict(<class 'list'>,
        {1: [[1, 1], [1, 2], [1, 3], [1, 4]],
         2: [[2, 1], [2, 2], [2, 3]],
         3: [[3, 1]],
         6: [[6, 1], [6, 2]]})

然后你可以从每个键中取出前两个[:2]值,并确保结果被展平并最终排序:

from itertools import chain

result = sorted(chain.from_iterable(x[:2] for x in groups.values()))

print(result)

哪个输出:

[[1, 1], [1, 2], [2, 1], [2, 2], [3, 1], [6, 1], [6, 2]]
© www.soinside.com 2019 - 2024. All rights reserved.