Преобразование одного упорядоченного списка в Python в словарь, Python - PullRequest
1 голос
/ 28 октября 2009

Я не могу найти элегантный способ начать с t и привести к s .

>>>t = ['a',2,'b',3,'c',4]
#magic
>>>print s
{'a': 2, 'c': 4, 'b': 3}

Решения, которые я придумала, кажутся менее элегантными:

s = dict()
for i in xrange(0, len(t),2): s[t[i]]=t[i+1]
# or something fancy with slices that I haven't figured out yet

Очевидно, что это легко решить, но, опять же, кажется, что есть лучший способ. Есть ли?

Ответы [ 6 ]

10 голосов
/ 29 октября 2009

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

def twobytwo(t):
  it = iter(t)
  for x in it:
    yield x, next(it)

d = dict(twobytwo(t))

или эквивалентно, и снова к itertools,

def twobytwo(t):
  a, b = itertools.tee(iter(t))
  next(b)
  return itertools.izip(a, b)

d = dict(twobytwo(t))

или, если вы настаиваете на том, чтобы быть на линии, в подходящем для сезона настроении "трюк или угощение":

d = dict((x, next(it)) for it in (iter(t),) for x in it)

я, я считаю это уловкой, но некоторые могут посчитать это удовольствием. Итак, я нахожу такие вещи страшными, но, по-видимому, в США примерно в это время года вещи должны быть; -).

По сути, проблема сводится к тому, «как пройти список 2 элементов за раз», потому что dict очень рад взять последовательность из 2 кортежей и превратить ее в словарь. Все решения, которые я здесь показываю, гарантируют, что только O(1) будет использовано дополнительное пространство (за пределами пробела, очевидно, O(N), что, конечно, необходимо для списка ввода и вывода dict).

Предложенный подход в документах (все должны быть знакомы с этой страницей, рецепты itertool) - это функция pairwise на этой странице, которая в основном является второй, которую я предложил здесь. Я думаю, что каждый каталог site-packages должен содержать файл iterutils.py с этими рецептами (жаль, что этот файл уже не является частью stdlib python! -).

9 голосов
/ 28 октября 2009

Та же идея, что и Ответ Лукаша Лалинского , другая идиома:

>>> dict(zip(*([iter(t)] * 2)))
{'a': 2, 'c': 4, 'b': 3}

Используются функции dict, zip и iter. Преимущество перед ответом Лукаша в том, что оно работает для любого повторяемого элемента. Как это работает:

  1. iter(t) создает итератор для списка t.
  2. [iter(t)] * 2 создает список с двумя элементами, которые ссылаются на один и тот же итератор.
  3. zip - это функция, которая принимает два итерируемых объекта и объединяет их элементы: первые элементы вместе, вторые элементы вместе и т. Д., Пока не будет исчерпан один итератор.
  4. zip(*([iter(t)] * 2)) приводит к тому, что один и тот же итератор для t будет передан как оба аргумента zip. Таким образом, zip возьмет первый и второй элемент t и объединит их в пару. А потом третий и четвертый. А потом пятый и шестой и т. Д.
  5. dict берет итерацию, содержащую (key, value) пар, и создает из них dctionary.
  6. dict(zip(*([iter(t)] * 2))) создает словарь в соответствии с запросом OP.
7 голосов
/ 28 октября 2009

Не совсем эффективно, но если вам не нужно это для очень больших списков:

dict(zip(t[::2], t[1::2]))

Или ваша версия с использованием генератора:

dict(t[i:i+2] for i in xrange(0, len(t), 2))
6 голосов
/ 28 октября 2009

Ребята, ребята, используйте itertools. Ваши пользователи с небольшим объемом оперативной памяти будут благодарны вам, когда списки станут большими.

>>> from itertools import izip, islice
>>> t = ['a',2,'b',3,'c',4]
>>> s = dict(izip(islice(t, 0, None, 2), islice(t, 1, None, 2)))
>>> s
{'a': 2, 'c': 4, 'b': 3}

Может выглядеть не очень красиво, но не будет делать ненужные копии в памяти.

2 голосов
/ 31 мая 2010

Использование модуля stream :

>>> from stream import chop
>>> t = ['a',2,'b',3,'c',4]
>>> s = t >> chop(2) >> dict
>>> s
{'a': 2, 'c': 4, 'b': 3}

Следует отметить, что этот модуль довольно неясен и на самом деле не "играет по правилам" того, что обычно считается политкорректным Python. Так что, если вы только изучаете Python, пожалуйста, не идите по этому пути; придерживайтесь того, что находится в стандартной библиотеке.

1 голос
/ 28 октября 2009
dict(zip(t[::2], t[1::2]))

наверное, не самый эффективный. работает на питоне 3; вам может понадобиться импортировать zip в python 2.x

...