Сопоставление значений Python в списке по группам

#python #list #mapping

Вопрос:

У меня есть следующее:

 mylist = ['A','A','A','B','B','C']

colors = ['r','g','b','w','y']
 

Я хочу, чтобы все одинаковые элементы в моем списке получали один и тот же цвет с начала списка цветов, поэтому результат будет таким:

 result = ['r','r','r','g','g','b']
 

Цвета, w и y будут проигнорированы. Похоже, не удается правильно настроить отображение.

Я пытался:

 result = [[y for y in colors if set(mylist) == x] for x in mylist]
 

Редактировать: чтобы сделать это более ясным, [‘r’,’g’,’b’,’w’,’y’] не всегда нужно сопоставлять с ABCDEF… мой список мог быть [«кошка»,»кошка»,»кошка»,»собака»,»собака»,»птица»]

Комментарии:

1. Всегда ли » [«r»,»g»,»b»,»w», «y»] » сопоставляется с ABCDE или это зависит от mylist заданного ?

Ответ №1:

Вы можете сначала создать сопоставление как a dict , а затем использовать его для получения результата

 mylist = ['A', 'A', 'A', 'B', 'B', 'C']
colors = ['r', 'g', 'b', 'w', 'y']

mapping = dict(zip(
    sorted(set(mylist)),
    colors
))
print(mapping)  # {'A': 'r', 'B': 'g', 'C': 'b'}

result = [mapping[l] for l in mylist]
print(result)  # ['r', 'r', 'r', 'g', 'g', 'b']
 

Комментарии:

1. Спасибо! Никогда не пользовался этой функцией zip, узнал что-то новое 🙂

Ответ №2:

Если вас не волнует порядок цветов:

 color_map = dict(zip(set(mylist), colors))
result = [color_map[item] for item in mylist]
 

Если вас волнует порядок цветов:

 from collections import OrderedDict

color_map = OrderedDict(zip(OrderedDict((item, True) for item in mylist), colors))
result = [color_map[item] for item in mylist]
 

Комментарии:

1. dict поддерживает порядок с py3.7 , так полезно ли его продолжать использовать OrderedDict ?

2. @azro Я, должно быть, пропустил это, спасибо тебе за это. Тем не менее, set(mylist) не соблюдает порядок, поэтому я могу либо использовать OrderedDict для условностей, либо написать свою собственную функцию uniq (которая будет более производительной). sort как и в вашем коде, зависит от того, что цвета уже отсортированы, что может иметь место, а может и не иметь.

Ответ №3:

Вы можете использовать счетчик, чтобы подсчитать, сколько раз значение появляется в вашем списке.

Затем используйте это сопоставление для заполнения списка результатов.

 from collections import Counter

mylist = ['A','A','A','B','B','C']
colors = ['r','g','b','w','y']
result = []
for idx, (_,v) in enumerate( Counter(mylist).items() ):
    result.extend( colors[idx] * v )
print(result)
 

Выход:

 ['r', 'r', 'r', 'g', 'g', 'b']
 

Примечание: Требуется Python > 3.7, в противном случае порядок диктанта не гарантируется — это также относится к другим ответам здесь, которые полагаются на > dict .

Ответ №4:

Для меня самым простым способом было бы:

 mylist = ['A', 'A', 'A', 'B', 'B', 'C']
colors = ['r', 'g', 'b', 'w', 'y']
result = []

for i, item in enumerate(sorted(set(mylist))):  # sets doesn't maintain the order, so its sorted alphabetically
    result.extend(colors[i] * mylist.count(item))

print(result)
 

Ответ №5:

Я бы предложил вместо этого использовать словарь, чтобы сохранить сопоставление:

 result = []
color_map = {}
idx = 0
for elt in mylist:
    if elt not in color_map.keys():
        color_map[elt] = colors[idx]
        idx  = 1
    result.append(color_map[elt])
 

Это также позволяет избежать повторения colors списка отдельно.