Страницы

Поиск по вопросам

воскресенье, 22 декабря 2019 г.

Сортировать список и удалить элементы, по которым велась сортировка

#python #python_3x #инспекция_кода


Имеется такой словарь:

{'L': [(568.0, 'John'), (208.0, 'Jack'), (88.0, 'Leopold'), (448.0, 'Sonny'), (328.0,
'Julian')],
 'R': [(1478.0, 'Diana'), (1238.0, 'Din'), (998.0, 'Mary'), (1118.0, 'Veronica'),
(1357.0, 'Richard')]}


С помощью этого кода:

for key in dictionary:
    dictionary[key].sort()
    for i in range(len(dictionary[key])):
        dictionary[key][i] = dictionary[key][i][1]


Он сортируется и становится вот такого вида:

{'L': ['Leopold', 'Jack', 'Julian', 'Sonny', 'John'],
 'R': ['Mary', 'Veronica', 'Din', 'Richard', 'Diana']}


То есть производится сортировка по возрастанию чисел (первых элементов кортежей),
после чего эти числа удаляются. Каким образом можно еще сортировать эти списки, чтобы
получился точно такой же результ? Мой код просто вырви глаз, если честно.
    


Ответы

Ответ 1



мне кажется использовать тут .items() или .values() излишне {k: [l[1] for l in sorted(_dict[k])] for k in _dict} дополню коментарием по ответу Ilia w495 Nikitin чем плохо использование lambda в map - это всегда длинее другого варианта # сравните result_list = map(lambda value: value[1], value_list) result_list = list(result_list) # тоже, но без map короче на 5 символов result_list = [value[1] for value in value_list] # даже если записать for+append в одну строку, все равно короче result_list = [] for value in value_list: result_list.append(value) # если функция для map уже определена(как str), тут и следует использовать map print('\n'.join(map(str, result_list)))

Ответ 2



Есть несколько вариантов это сделать. Например для начала по-другому организовать код, который вы написали. Например, можно сразу проходить по ключам и значениям for value in dictionary.values(): value.sort() for i in range(len(value)): value[i] = value[i][1] В вложенном цикле, не не обязательно итерироваться по range(len), можно воспользоваться enumerate. for value in dictionary.values(): value.sort() for i, (_, v) in enumerate(value): value[i] = v Дальше, можно было бы отказаться от конструкции value[i] = v и заменить ее например, на value += [v], но при текущей структуре кода это делать не очень удобно. Кроме того, главный минус всех вариантов в том — что мы модифицируем входные данные. Во многих случаях это недопустимо. Напишем функцию, которая возвращает новый словарь. def sorted_value_dict(value_dict): # Создаем выходной словарь. result_dict = dict() # Проходим по ключам и значениям в списке. for key, value_list in value_dict.items(): # Сортируем значения в списке value_list = sorted(value_list) # Список — значение по ключу в словаре result_list = list() # Проходим по списку кортежей, # и оставляем только вторые элементы. for _, value in value_list: result_list += [value] # Кладем значение выходной словарь. result_dict[key] = result_list return result_dict Заменим вложенный цикл на map: def sorted_value_dict(value_dict): # Создаем выходной словарь. result_dict = dict() # Проходим по ключам и значениям в списке. for key, value_list in value_dict.items(): # Сортируем значения в списке value_list = sorted(value_list) # Проходим по списку кортежей, # и оставляем только вторые элементы. result_list = map(lambda value: value[1], value_list) # Кладем значение выходной словарь. result_dict[key] = result_list return result_dict Заменим внешний цикл на map: def sorted_value_dict(value_dict): result_dict = dict( map( lambda (k, v): (k, map(lambda t: t[1], sorted(v))), value_dict.items() ) ) return result_dict Выглядит весьма компактно, но кажется не очень читаемым. Лично я бы предпочел решение через генераторы. def sorted_value_dict(value_dict): # Получаем последовательность пар (<ключ>, <новое значение>). sequence = tuple_seq(value_dict) # Преобразуем последовательность к словарю. return dict(sequence) def tuple_seq(value_dict): # Проходим по ключам и значениям в списке. for key, value_list in value_dict.items(): # Получаем последовательность вторых элементов. sorted_sequence = sorted_value_seq(value_list) # Преобразуем последовательность к списку. sorted_list = list(sorted_sequence) # Порождаем пару (<ключ>, <новое значение>). yield key, sorted_list def sorted_value_seq(value_list): # Сортируем последовательность исходных пар. value_list = sorted(value_list) # Проходим по списку пар. for _, value in value_list: # Порождаем второй элемент пары. yield value В коде мы получаем несколько функций, но само по себе это может оказаться плюсом, для повторного использования.

Ответ 3



Мне в подобных случаях нравится использовать comprehensions: # dct - исходный словарь res = {key: [name for _, name in sorted(lst, key=lambda tpl: tpl[0])] for key, lst in dct.items()} UPD: С учётом замечания в комментарии к ответу, для данного случая код можно записать ещё проще: res = {key: [name for _, name in sorted(lst)] for key, lst in dct.items()}

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

Отправить комментарий