Используйте понимание списка, чтобы заменить дубликаты, основанные на условии, используя другой список - PullRequest
0 голосов
/ 28 февраля 2019

Вероятно, это проще проиллюстрировать на примере.

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. Я хочу назначить списку C наименьший элемент из каждогодубликат элемента в A (где наименьшее значение получается из соответствующих значений в списке 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 голосов
/ 28 февраля 2019

Да, это возможно в одной строке.

[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]
0 голосов
/ 28 февраля 2019

Если вам нужен один вкладыш, это работает, при условии, что мой комментарий является правильной интерпретацией:

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

Чтобы разбить его, у вас есть самое внутреннее понимание списка, проходящее по индексам и значениям в A, затем следующее понимание списка снова перебирает все значения в A (сохраняя их в y) и используется как условие для предыдущего упомянутого списка.
Затем вы используете этот список индексов, чтобы получитьвсе элементы в B (используя j) и, наконец, получить min в этом списке. Перечисление

возвращает индексы и значения в ind и x соответственно.

0 голосов
/ 28 февраля 2019

Если вы не возражаете против использования дополнительной библиотеки Python с именем Pandas, вы можете сделать следующее:

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]
0 голосов
/ 28 февраля 2019

Вы можете использовать следующий метод:

>>> 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 из tuple s в dict дублирующиеся ключи перезаписываются последним.

...