# list 2 dict?

O

#### Octavian Rasnita

Hi,

If I want to create a dictionary from a list, is there a better way than the long line below?

l = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

d = dict(zip([l[x] for x in range(len(l)) if x %2 == 0], [l[x] for x in range(len(l)) if x %2 == 1]))

print(d)

{8: 'b', 1: 2, 3: 4, 5: 6, 7: 'a'}

Thanks.

Octavian

H

#### Hrvoje Niksic

Octavian Rasnita said:
If I want to create a dictionary from a list, is there a better way than the long line below?

l = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

d = dict(zip([l[x] for x in range(len(l)) if x %2 == 0], [l[x] for x in range(len(l)) if x %2 == 1]))

print(d)

{8: 'b', 1: 2, 3: 4, 5: 6, 7: 'a'}

it = iter(l)
d = dict(izip(it, it))

izip is the iterator equivalent of zip, import it from itertools. (Or, if

It can be written in a single short line, at the cost of additional
obfuscation:

d = dict(izip(*[iter(l)]*2))

G

#### Glazner

Hi,

If I want to create a dictionary from a list, is there a better way than the long line below?

l = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

d = dict(zip([l[x] for x in range(len(l)) if x %2 == 0], [l[x] for x in range(len(l)) if x %2 == 1]))

print(d)

{8: 'b', 1: 2, 3: 4, 5: 6, 7: 'a'}

Thanks.

Octavian

this is efficient

l = [1,2,3,4,5,6]{1: 2, 3: 4, 5: 6}

D

#### DevPlayer

An adaptation to Hrvoje Niksic's recipe

Use a dictionary comprehention instead of a list comprehension or
function call:

lyst = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

it = iter( lyst )
dyct = {i:it.next() for i in it} # I'm using {} and not [] for those
with tiny fonts.

#print dyct
{8: 'b', 1: 2, 3: 4, 5: 6, 7: 'a'}

Of course check for an "even" number of elements to the original list
to avoid exceptions or dropping the last element on traps.

P

#### Paul Rubin

Octavian Rasnita said:
If I want to create a dictionary from a list...
l = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

dict(l[i:i+2] for i in xrange(0,len(l),2))

seems simplest to me.

D

#### DevPlayer

or only convert the item when you need it leaving the lists as the
source

lyst = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

func = lambda alist, index: dict([(lyst[index*2],
lyst[(index*2)+1]),])

func(lyst, 0)
{1: 2}

func(lyst, 2)
{5: 6}

##########------------
or as a function
def func(lyst, index):
return dict(((lyst[index], lyst[index+1]),))

D

#### DevPlayer

Here is something totally the opposite of a nice one liner:

A hackish module with a bloated generator. Feel free to comment, so I
can learn the errors of my ways. Try not to be too mean though. Try to
think of the attached file as a demonstration of ideas instead of good
coding practices.

Don't be afraid to mention the good points too.

I tried to send an email with an attachment (to hide my shame) but I
kept getting email rejections.

# =======================================================
# list2dict.py

# list item to dict item generator
# I forget if generators are thread safe

# 2011-01 Jan-03
#

def check_slice_bounds(list_len, start, stop, step):
"""Incomplete slice checker."""

# -----------------------------
# force step to be non-None
if step is None:
step = 1

# -----------------------------
# force step to be non-zero
if step == 0:
step = 1

# -----------------------------
# in iterating over list to be converted to dict
# where list == [key, value, key, value] or in case swap==True
# list = [value, key, value, key]
# actual stepping is one for key, and plus one more for value
step = step * 2

# -----------------------------
# force step to be smaller then size of list or -size of list

if step > 0:
if step > list_len:
step = list_len
else:
if step < -list_len:
step = -list_len

# -----------------------------
# force step to be even for key, value iteration
if step % 2 == 1:
if step > 0:
step = step - 1
else:
step = step + 1

# -----------------------------
# set start to default; depending on step direction (+x vs -x)

if start is None:
if step > 0:
start = 0
elif step == 0:
start = 0
stop = start
else:
start = -1

# -----------------------------
# set stop to default; depending on step direction (+x vs -x)

if stop is None:
if step > 0:
stop = list_len-1
elif step == 0:
stop = start
else:
stop = -list_len

# -----------------------------
# convert "start" to equivelent positive index

if start < 0:
if start < -list_len:
raise IndexError("IndexError: list index out of range:",
start)
else:
start = list_len + 1 + start

# -----------------------------
# convert "stop" to equivelent positive index

if stop < 0:
if stop < -list_len:
raise IndexError("IndexError: list index out of range:",
stop)
else:
stop = list_len + 1 + stop

return (start, stop, step)

def gen(lyst, dyct=None, start=None, stop=None, step=None,
swap=False):
"""
lyst == list to convert to dict
dyct == external dict to be updated
start == starting index
stop
step == amount to move index by; usually +1 or -1 (times 2)
could be a float if clever enough.
if step equals zero it is converted to 1 to prevent
an infinite loop.
step will be reset to be an index inbounds of a list len()
swap 2nd item with the first item in the yield
"""

# -----------------------------
# Force into bool True or False from equivelent values

if swap == True: swap = True
else: swap = False

# -----------------------------
# check and set lyst slice/index bounds of start, stop, step

start, stop, step = check_slice_bounds(len(lyst), start, stop,
step)

# -----------------------------
index = start
# -----------------------------
while 0 <= index < len(lyst):
next = index + 1

if next == len(lyst):
value = None
else:
value = lyst[next]
key = lyst[index]

# -----------------------------
# update external dict if given

if dyct is not None:
dyct[key] = value

# -----------------------------
# effectively sway key with value == index, index+1 to index
+1, index

if swap:
newindex = yield (value,key)
else:
newindex = yield (key,value)

# -----------------------------
# process "newindex" variable if caller does a
# gen.send(some_list_index) externally

if newindex is None:
index = index + (step)
elif 0 <= newindex < len(lyst):
# fix this to allow for negative index for negative
stepping
# but don't forget to convert it to its corrosponding
# positive index
index = newindex
else:
# fix this so it doesn't error on index 0
#raise IndexError("Index is out of range:", index)
pass

# -----------------------------
# Ungracefully coerce end of iteration
if step > 0:
if index > stop:
# fix to raise StopIteration
break
else:
if index < stop:
# fix to raise StopIteration
break

# Example usage
testlist = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

# --------------------
d = {}
e = {y[0]:y[1] for y in gen(testlist,d)}
print d
print d
print 'next demo1'

# --------------------
d = {}
e = {y[1]:y[0] for y in gen(testlist,d)}
f = {y[0]:y[1] for y in gen(testlist,d, swap=True)}
print d
print e
print f
print 'next demo2'

# --------------------
d = {}
for x in gen(testlist,d):
print x
print d
print 'next demo3'

# --------------------
d = {}
e = [y for y in gen(testlist,d,swap=True)]
print d
print e
print 'next demo4'

# --------------------
d = {}
e = gen(testlist,d)
try:
while e.next(): pass
except:
pass
print d
#print 'next demo'

D

#### DevPlayer

The shorter version:
This doesn't need any x = iter(list) line. perhaps more useful if you
have a bunch of lists to be converted through out your code.

def dictit(lyst):
i = 0
while i < len(lyst):
yield lyst, lyst[i+1]
i = i + 2

l = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

{d[0]:d[1] for d in dictit(l)} 3 again a dict comprehension

func = lambda l: {k[0]:k[1] for k in dictit(l)}
d = func(l)

M

#### MRAB

Octavian Rasnita said:
If I want to create a dictionary from a list...
l = [1, 2, 3, 4, 5, 6, 7, 'a', 8, 'b']

dict(l[i:i+2] for i in xrange(0,len(l),2))

seems simplest to me.

Or:

dict(zip(l[0 : : 2], l[1 : : 2]))