2013-04-22 2 views
2

У меня есть несколько списков, которые соответствуют друг другу, как это:Как сделать словарь из нескольких списков?

ID_number = [1, 2, 3, 4, 5, 6, ...] 
x_pos = [43.2, 53.21, 34.2, ...] 
y_pos = [32.1, 42.1, 8.2, ...] 
z_pos = [1.3, 67.1, 24.3, ...] 

т.д.

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

dictionary = {'id1':[x_pos1, y_pos1, z_pos1], 'id2':[x_pos2, y_pos2, z_pos2], ...} 

где ключ идентификационного номера и значение представляет собой список, содержащий соответствующие данные для этого идентификационного номера. Как я могу сделать это эффективно в python?

ответ

2

zip() весьма полезен для достижения этой цели. Например:

>>> ID_number = [1,2,3] 
>>> x_pos = [43.2, 53.21, 34.2] 
>>> y_pos = [32.1, 42.1, 8.2] 
>>> z_pos = [1.3, 67.1, 24.3] 
>>> dict((x[0], x[1:]) for x in zip(ID_number, x_pos, y_pos, z_pos)) 
{1: (43.200000000000003, 32.100000000000001, 1.3), 2: (53.210000000000001, 42.100000000000001, 67.099999999999994), 3: (34.200000000000003, 8.1999999999999993, 24.300000000000001)} 

Если набор данных достаточно велик, вы можете избежать создания zip() «s совершенно новую копию всего набора данных с помощью itertools.izip() вместо этого. Эта функция вернет итератор, который будет обеспечивать каждый заархивированный элемент при запросе, вместо того, чтобы хранить всю новую структуру в памяти. (Результат будет таким же, но она должна быть быстрее на больших наборах данных.)

>>> import itertools 
>>> dict((x[0], x[1:]) for x in itertools.izip(ID_number, x_pos, y_pos, z_pos)) 
{1: (43.200000000000003, 32.100000000000001, 1.3), 2: (53.210000000000001, 42.100000000000001, 67.099999999999994), 3: (34.200000000000003, 8.1999999999999993, 24.300000000000001)} 
4

Используйте zip дважды:

сравнение
>>> ids = [1,2,3,4] 
>>> x_pos = [1.32, 2.34, 5.56, 8.79] 
>>> y_pos = [1.2, 2.3, 3.4, 4.5] 
>>> z_pos = [3.33, 2.22, 10.98, 10.1] 
>>> dict(zip(ids, zip(x_pos, y_pos, z_pos))) 
{1: (1.32, 1.2, 3.33), 2: (2.34, 2.3, 2.22), 3: (5.56, 3.4, 10.98), 4: (8.79, 4.5, 10.1)} 

Timing с genexp:

>>> import timeit 
>>> timeit.timeit('dict(zip(ids, zip(x_pos, y_pos, z_pos)))', 'from __main__ import ids, x_pos, y_pos, z_pos') 
1.6184730529785156 
>>> timeit.timeit('dict((x[0], x[1:]) for x in zip(ids, x_pos, y_pos, z_pos))', 'from __main__ import ids, x_pos, y_pos, z_pos') 
2.5186140537261963 

Таким образом, использование zip дважды примерно в 1,5 раза быстрее, чем использование выражения генератора. Очевидно, что результаты зависят от размера итераций, но я вполне уверен в том, что использование double zip, по крайней мере, на CPython 2 всегда будет быстрее, чем явные контуры. Генераторы исключений или for циклов требуют гораздо больше работы для интерпретатора, чем одиночный вызов zip, что устраняет некоторые издержки из процесса итерации.

Использование itertools.izip вместо zip не очень сильно изменяет тайминги, но для больших наборов данных намного эффективнее память.

0
dictionary = {'id' + str(i): [x, y, z] 
       for i, x, y, z in zip(ID_number, x_pos, y_pos, z_pos)} 

для больших наборов данных, вероятно, быстрее, с itertools 'izip().

Смежные вопросы