Как ускорить замену элементов в списке Python?
Есть список mapping_pixels=[(68, 68, 125, 255), (68, 68, 125, 255), (71, 72, 86, 255), .....] в котором 1280*1280 элементов и есть список unique_pixels[] из множества уникальных элементов списка mapping_pixels[], коих 3800 шт. Надо все элементы списка mapping_pixels[] заменить на индекс элементов списка unique_pixels[], если значения совпадают. Я сделал две итерации и сравниваю по элементу, но это очень долго. Подскажите способ что бы процесс не занимал много времени.
from PIL import Image
def create_map2():
im = Image.open('sprite/map3.png').convert('RGBA')
mapping_pixels = list(im.getdata())
mapping = []
row = []
unique_pixels = list(set(list(mapping_pixels)))
step = 0
unique_pixels_dict = {
value: i
for i, value in enumerate(unique_pixel)
}
for pixel in mapping_pixel:
if len(row) == im.width:
mapping.append(row)
row = []
row.append(unique_pixels_dict[pixel])
return im.width, im.height, list(set(list(im.getdata()))), mapping
map2 = create_map2()
Ответы (2 шт):
Сударь, вам надо учиться задавать понятные вопросы :)
- "тот же самый список b[] без повторения элементов в нём 3800 элементов" – это скорее не тот же самый, а "список b из множества уникальных элементов списка a, коих 3800 шт".
- Чтобы упростить жизнь отвечающим, стоит связать вашу абстрактную формулировку вопроса с кодом, а не вынуждать перечитывать вопрос пару раз: список
aв коде этоmap_pixel, аbэтоl. lплохое название, я бы заменил на что-то более осмысленное вродеunique_values.- Насчёт плохой практики использования встроенных значений вроде
mapкак имён переменных вам уже подсказали.
Проблема же здесь в том, что из-за вложенности циклов сложность алгоритма выходит квадратичной, что легко решается использованием словаря с маппингом значений из списка b в их индексы:
map_pixels = list(...)
unique_values = list(set(map_pixels))
unique_values_indices = {
value: i
for i, value in enumerate(unique_values)
}
row = []
for pixel in map_pixels:
row.append(unique_values_indices[pixel])
Кстати, "Special cases aren't special enough to break the rules", и ваш особый кейс с (68, 68, 122, 255) можно реализовать более грамотно:
first_values = [(68, 68, 122, 255)]
unique_values = first_values + list(set(map_pixels) - set(first_values))
Таким образом, это особое значение всегда будет иметь нулевой индекс, зато не потребует отдельной обработки в цикле, а при желании эту штуку легко масштабировать добавив в список first_values дополнительные первые значения.
попробовал ускорить
from PIL import Image
import numpy as np
def create_map2():
im = Image.open('sprite/map3.png').convert('RGBA')
mapping_pixel = (list(im.getdata()))
unique_pixel = (list(set(list(im.getdata()))))
unique_pixel_dict = {
value: i
for i, value in enumerate(unique_pixel)
}
mapping = list(map(lambda x: unique_pixel_dict[x], mapping_pixel))
mapping = np.array(mapping)
mapping = self.mapping.reshape(im.height, im.width)
return im.width, im.height, unique_pixel , mapping
map2 = create_map2()
