使用列表推导根据条件使用其他列表替换重复项

时间:2019-02-28 03:52:16

标签: python list-comprehension

通过示例进行说明可能更容易。

A = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
B = [0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.03, 0.04, 0.001, 0.001, 0.0003, 0.0003]

我有上面的两个列表。

A中的每个元素都重复了几次。每个元素的多重性可以不同(不必按此处顺序排列)。

B包含与A相同数量的元素。我想将A中每个重复元素中的最小元素分配给列表C(其中最小值来自B列表中的对应值。因此对于前4个元素,则为0.1,对于接下来的4个元素,在此示例中为0.01,对于最后4个元素,其为0.0003的重复值,并且对于每个重复元素而言都是此值。)

我想获得以下列表。

C = [0.1, 0.1, 0.1, 0.1, 0.01, 0.01, 0.01, 0.01, 0.0003, 0.0003, 0.0003, 0.0003]

由于我正在使用的代码已经广泛使用列表推导,因此我想使用相同的方法。

这可能吗?

这建议吗?

我熟悉简单的条件,例如

C = A[B < 0.0005]

给予

C = [3]

但是对于如何继续此处并没有一个明确的想法。

4 个答案:

答案 0 :(得分:2)

您可以使用以下方法:

>>> A = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
>>> B = [0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.03, 0.04, 0.001, 0.001, 0.0003, 0.0003]
>>> AB = zip(A, B)
>>> AB_sorted = sorted(AB, key=lambda i: (i[0], -i[1]))
>>> AB_dict = dict(AB_sorted)
>>> C = [AB_dict[i] for i in A]
>>> C
[0.1, 0.1, 0.1, 0.1, 0.01, 0.01, 0.01, 0.01, 0.0003, 0.0003, 0.0003, 0.0003]

之所以可行,是因为当您将list的{​​{1}}转换为tuple时,重复的密钥会被最后一个密钥覆盖。

答案 1 :(得分:1)

如果您想要一支班轮,那么这可行,假设我的评论是正确的解释:

[min([B[j] for j in [ind for ind,x in enumerate(A) if x==y]]) for y in A]

要进行分解,请对A中的索引和值进行最内层的列表理解,然后再次对A中的所有值进行下一个列表理解(将它们存储在{{ 1}}),并用作前面提到的列表的条件。
然后,您可以使用该索引列表来获取y中的所有元素(使用B)并最终获得该列表上的j

enumerate将索引和值分别返回到minind中。

答案 2 :(得分:1)

如果您不介意使用名为Pandas的其他Python库,则可以执行以下操作:

import pandas as pd
A = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
B = [0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.03, 0.04, 0.001, 0.001, 0.0003, 0.0003]
df = pd.DataFrame([A, B]).T.rename(columns={0: 'A', 1: 'B'})
req_dict = {key: value for key, value in df.groupby('A')['B'].min().iteritems()}
print(df['A'].replace(req_dict))

输出:

[0.1, 0.1, 0.1, 0.1, 0.01, 0.01, 0.01, 0.01, 0.0003, 0.0003, 0.0003, 0.0003]

答案 3 :(得分:0)

是的,可以在一行中。

[min(y for x, y in zip(A, B) if z == x) for z in A]

这将产生此列表

[0.1, 0.1, 0.1, 0.1, 0.01, 0.01, 0.01, 0.01, 0.0003, 0.0003, 0.0003, 0.0003]