Сортировка словаря в список

Уже есть много вопросов о сортировке словарей, но я не могу найти правильный ответ на мой вопрос.

У меня есть словарь v:

v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0} 

Мы должны превратить словарь v в отсортированный список.

 lijst(v) = [1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5] 

Я пробовал работать с этим кодом:

 def lijst(x): return sorted(x.items(), key=lambda x: x[1]) 

Это список, который я получаю:

 lijst(v) = [(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)] 

Кто-нибудь знает, как преобразовать это в список значений, отсортированных по порядку их ключа, с отсутствующими значениями, заполненными нулем?

7 Solutions collect form web for “Сортировка словаря в список”

Просто используйте itertools.chain.from_iterable чтобы сгладить ваш результат (список кортежей):

 >>> import itertools >>> list(itertools.chain.from_iterable([(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)])) [1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0] 

Если я неправильно понял ваш первоначальный запрос, и словарь представляет собой «разреженный вектор» (где ключи являются индексами), вы можете просто заполнить список, содержащий только нули:

 >>> res = [0.0]*(max(v)+1) # create a dummy list containing only zeros >>> for idx, val in v.items(): # populate the requested indices ... res[idx] = val >>> res [1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5] 

Или, если у вас есть NumPy, вы также можете избежать использования -loop:

 >>> import numpy as np >>> arr = np.zeros(max(v)+1) >>> arr[list(v.keys())] = list(v.values()) >>> arr array([ 1. , -2. , 0. , 4. , 0. , 0. , 0. , 0. , 0. , 0. , 3.5]) 

Последний подход основан на том факте, что, хотя порядок keys и values произволен, они тем не менее напрямую соответствуют, пока нет модификации словаря:

Ключи и значения повторяются в произвольном порядке, который является неслучайным, варьируется в разных реализациях Python и зависит от истории вставки и удаления словаря. Если ключи, значения и представления элементов повторяются без каких-либо промежуточных изменений в словаре, порядок элементов будет напрямую соответствовать.

Источник 4.10.1. Объекты просмотра словаря

Вы можете попробовать это, используя chain из itertools :

 from itertools import chain v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0} final_output = list(chain(*sorted(v.items(), key=lambda x: x[1]))) 

Вывод:

 [1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0] 

Один из способов конкатенировать пары (ключ, значение) – с помощью sum() с начальным значением:

 >>> sum(sorted(v.items(), key=lambda x:x[1]), ()) (1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0) 

Это возвращает кортеж. Передайте его в list() если вам действительно нужен список.

PS Как справедливо отметили @MSeifert в комментариях, это почти наверняка имеет O (n ** 2) временную сложность, тогда как list(chain(...)) , вероятно, амортизируется линейным.

Другой вариант – использовать yield from синтаксиса, введенного в Python 3.3 :

 >>> lst = [(1, -2.0), (0, 1.0), (10, 3.5), (3, 4.0)] >>> list([(yield from tup) for tup in lst]) [1, -2.0, 0, 1.0, 10, 3.5, 3, 4.0] >>> 

Caveat : Обратите внимание, что использование этого метода внутри понимания списка может не быть «официальным синтаксисом», а некоторые (включая Guido) считают его ошибкой .

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

если вы хотите сохранить держатели 0.0 мест для предметов, которые недоступны:

 [v.get(i, 0.0) for i in range(max(v.keys())+1)] 

вывод:

 [1.0, -2.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.5] 

Если вы не хотите держателей 0.0 мест, вы можете использовать:

 [v.get(i) for i in range(max(v.keys())+1) if v.get(i) is not None] 

вывод:

 [1.0, -2.0, 4.0, 3.5] 

Объяснение:

когда вы используете range() он будет генерировать отсортированный список, поэтому вам не придется беспокоиться о сортировке, а затем попытается получить элементы из словаря в соответствии с этим списком. В первом примере, если ключ не существует, будет возвращен 0.0 , а во втором примере None будет возвращен и будет проигнорирован из if-statement в выражении.

РЕДАКТИРОВАТЬ:

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

 [v[i] for i in range(max(v.keys())+1) if i in v] 

Это позволит избежать вызова v.get(i) дважды.

Это не строго отвечает на вопрос, а пытается понять, чего вы пытаетесь достичь. Если вы пытаетесь реализовать разреженные векторы, прежде чем тратить время на новую реализацию, вы можете посмотреть в scipy.sparse .

Например:

 from scipy.sparse import dok_matrix v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0} m = dok_matrix((11,1)) m.update(v) 

Преимущество разреженных матриц состоит в том, что (в зависимости от доли ненулевых элементов) они могут занимать меньше памяти и / или допускать более быстрые вычисления.

 v = {3:4.0, 1:-2.0, 10:3.5, 0:1.0} print sorted(v.values()) 

результат

 [-2.0, 1.0, 3.5, 4.0] 
  • return vs print list
  • Присоедините список списков вместе в один список в Python
  • Список Python: это лучший способ удалить дубликаты при сохранении порядка?
  • Сортировка элементов словаря в списке
  • Использовать список вложенных индексов для доступа к элементу списка
  • Преобразование списка чисел в строки
  • Python: как преобразовать список значений словарей в int / float из строки?
  • Python: фильтрация списков по индексам
  • Python - лучший язык программирования в мире.