How to convert list of key-value tuples into dictionary? - python

I have a list that looks like:
[('A', 1), ('B', 2), ('C', 3)]
I want to turn it into a dictionary that looks like:
{'A': 1, 'B': 2, 'C': 3}
What's the best way to go about this?
EDIT: My list of tuples is actually more like:
[(A, 12937012397), (BERA, 2034927830), (CE, 2349057340)]
I am getting the error ValueError: dictionary update sequence element #0 has length 1916; 2 is required

>>> dict([('A', 1), ('B', 2), ('C', 3)])
{'A': 1, 'C': 3, 'B': 2}

Your error:
Why you are getting the ValueError: dictionary update sequence element #0 has length 1916; 2 is required error:
The answer is that the elements of your list are not what you think they are. If you type myList[0] you will find that the first element of your list is not a two-tuple, e.g. ('A', 1), but rather a 1916-length iterable.
Once you actually have a list in the form you stated in your original question (myList = [('A',1),('B',2),...]), all you need to do is dict(myList).
[2021 edit: now also answers the actual question asked, not the intended question about the specific error:]
In general:
Either use the usual dict(iterableOrMapping) constructor, or use the dict comprehension {someExpr(k,v) for k:v in iterable} syntax:
>>> example1 = [('A',1), ('B',2), ('C',3)]
>>> dict(example1)
{'A': 1, 'B': 2, 'C': 3}
>>> {x:x**2 for x in range(3)}
{0: 0, 1: 1, 2:4}
# inline; same as example 1 effectively. may be an iterable, such as
# a sequence, evaluated generator, generator expression
>>> dict( zip(range(2),range(2)) )
{0: 0, 1: 1, 2:2}
A Python dictionary is an O(1)-searchable unordered collection of pairs {(key→value), ...} where keys are any immutable objects and values are any object.
Keys MUST implement the .__eq__()
and .__hash__() methods to be usable in the dictionary. If you are thinking of implementing this, you are likely doing something wrong and should maybe consider a different mapping data structure! (Though sometimes you can get away with wrapping the keys in a different wrapper structure and using a regular dict, this may not be ideal.)
Intermediate or advanced programmers who wish to implement a 'frozen' or 'immutable' type, or one which masquerades as one, must be very careful of implications or else your program will be wrong with extremely subtle and near-impossible-to-find bugs:
You can't use a dict if you allow yourself to mutate the object later such that its notion of equality might change. Objects considered equal must always have __eq__ return True and have __hash__ return identical values.
The methods must exactly obey the spec. This means that:
For novices: Hash functions(wikip.) let you get a false-positive or true-positive result; hash(x)==hash(y) means x MIGHT equal y and the internal python code must then check x==y (.__eq__) to confirm it's a true-positive and not a false-positive. This allows O(1) lookup.
For novices: It is critically important that the __hash__ value not change for any reason once the object is in its final state. If you cannot guarantee both this and hash(x)!=hash(y) implies x!=y, you should not be using a dict.
One might consider a different type of mapping rather than modifying the data itself. This can be equivalent to writing a wrapper object, at the cost of using a library. This is usually not necessary.
For experts: It should also be noted that the hashes of some default objects are salted and may change between python invocations and versions (this may be a gotcha if you store or network-communicate data in any way that contains python hashes; they are an internal detail that should be regenerated on each process startup).
Python has a bunch of built-in frozen datastructures such as namedtuple, frozenset, etc., but they are sometimes harder to work with. tuple is the basic frozen variant of the basic list structure (which would let you store a {(1, 2): 3, (4, 5): 6}). It also has some variants of the dict structure. If you want to get a map from "frozen dicts" to values, frozendict doesn't exist except as a third-party library, but you can extract the dict's .items() as a an unordered frozenset of tuples.

Have you tried this?
>>> l=[('A',1), ('B',2), ('C',3)]
>>> d=dict(l)
>>> d
{'A': 1, 'C': 3, 'B': 2}

Here is a way to handle duplicate tuple "keys":
# An example
l = [('A', 1), ('B', 2), ('C', 3), ('A', 5), ('D', 0), ('D', 9)]
# A solution
d = dict()
[d [t [0]].append(t [1]) if t [0] in list(d.keys())
else d.update({t [0]: [t [1]]}) for t in l]
d
OUTPUT: {'A': [1, 5], 'B': [2], 'C': [3], 'D': [0, 9]}

If Tuple has no key repetitions, it's Simple.
tup = [("A",0),("B",3),("C",5)]
dic = dict(tup)
If tuple has key repetitions.
tup = [("A",0),("B",3),("C",5),("A",9),("B",4)]
dic = {}
for i, j in tup:
dic.setdefault(i,[]).append(j)
Or:
from collections import defaultdict
tup = [("A",0),("B",3),("C",5),("A",9),("B",4)]
dic = defaultdict(list)
for i, j in tup:
dic[i].append(j)

Another way using dictionary comprehensions,
>>> t = [('A', 1), ('B', 2), ('C', 3)]
>>> d = { i:j for i,j in t }
>>> d
{'A': 1, 'B': 2, 'C': 3}

l=[['A', 1], ['B', 2], ['C', 3]]
d={}
for i,j in l:
d.setdefault(i,j)
print(d)

Related

Understanding dictionary assignment with tuple and list

I am a python beginner and I recently learned about dictionary assignment.
Here's what I am attempting
my_list = [[1, 4], [2, 2],[5,1]]
lists = dict(my_list)
print(lists) # Prints {1:4,2:2,5:1}
my_list = [(1, 4), (2, 2),(5,1)]
lists = dict(my_list)
print(lists) # Prints {1:4,2:2,5:1}
my_list = [[1, 4], (2, 2),{5,1}]
lists = dict(my_list)
print(lists) # Prints {1:5,2:2}
I am unable to explain why we are getting this weird answer in example 3.
Kindly help and explain.
{5, 1} is a set and, as such, inherently unordered. It is, somewhat depending on your Python implementation, unpredictably iterated as either 1->5 or 5->1. If you catch the first case, your dict instantiation is equivalent to:
lists = dict([(1, 4), (2, 2), (1, 5)])
or, even more verbose and obvious
lists = {}
lists[1] = 4
lists[2] = 2
lists[1] = 5 # overrides first binding of 1
Since there can be no duplicate keys in a dict, the last key binding for a repeated key "wins".

Behaviour of set that stores tuples, Python

I'd like to create a set of tuples, but have been encountering some behaviour that I don't understand. For example:
>>> b=set()
>>> b.add((1,2))
>>> b.add((4,5))
>>> b
{(1, 2), (4, 5)}
# all fine
>>> f = set((1,2,3))
>>> f
{1, 2, 3}
# ?
>>> b=set().add((1,2))
>>> b
# b is empty?
Can someone help me understand this behaviour? My understanding is that tuples are hashable, so I should be able to store them in a set. I'm using Python 3.
You are confusing different things.
set() takes an iterable and creates a set from the contents.
If you want to create a set with a single tuple, pass in an iterable with that single tuple:
>>> set([(1, 2, 3)])
{(1, 2, 3)}
It's better to use the {...} set literal syntax:
>>> {(1, 2, 3)}
{(1, 2, 3)}
set().add() updates a set in-place and returns None.
If you wanted to create an empty set and add to that, do so in two separate expressions:
>>> b = set()
>>> b.add((1, 2))
>>> b
{(1, 2)}
Neither of these two issues have anything to do with tuples being hashable.
set((1, 2, 3)) means a set of (1, 2, 3)'s elements. A set whose only element is (1, 2, 3) is {(1, 2, 3)}, not set((1, 2, 3)).
set.add modifies a set in place. If you want to add to a set, you need to store the set itself, then add to it, not store add's return value.

Getting single value from multiple values in dictionary

I have a dictionary like this
dic={10:(1,4),20:(2,4),30:(3,4)}
how to get 1,2,3 as output using dic.values() without using for loop.
This works:
>>> dic={10:(1,4),20:(2,4),30:(3,4)}
>>> [x[0] for x in dic.values()]
[1, 2, 3]
>>> # Or if you want that as a tuple
>>> tuple(x[0] for x in dic.values())
(1, 2, 3)
>>> # Or a string
>>> ",".join([str(x[0]) for x in dic.values()])
'1,2,3'
>>>
You should remember though that the order of dictionaries is not guaranteed. Meaning, the key/value pairs will not always be in the same order the you put them in.
To get disordered results in the order you want, you should look at sorted.
If you look at what dic.values() produces:
>>> dic={10:(1,4),20:(2,4),30:(3,4)}
>>> dic.values()
[(1, 4), (2, 4), (3, 4)]
Obviously you want the first element of each tuple.
You can use zip to get that without looping1.
>>> zip(*dic.values())[0]
(1, 2, 3)
As pointed out in comments, an even more efficient solution is:
>>> from itertools import izip
>>> next(izip(*dic.itervalues()))
(1, 2, 3)
Then you do not have to go all the way though creating several lists just to get the first element.
The order, of course, depends on the order of the keys in dic.
1 The 'without looping' is a silly distinction IMHO. Every solution either has an explicit or implicit loop in it...
Answer: You can't. You'll have to loop through the dictionary:
for v in d.values():
print v[0]
Or using a list comprehension:
[v[0] for v in d.values()]
This filtering methods are the best you can find :)
This solution is not any better than using iterators, but it has a different approach and maybe it is more suitable for complex tasks:
from operator import itemgetter
dic={10:(1,4),20:(2,4),30:(3,4)}
print map(itemgetter(0), dic.values())
gives:
[1, 2, 3]
How about using map here.
map(lambda x: x[0], dic.values())

Obtaining length of list as a value in dictionary in Python 2.7

I have two lists and dictionary as follows:
>>> var1=[1,2,3,4]
>>> var2=[5,6,7]
>>> dict={1:var1,2:var2}
I want to find the size of the mutable element from my dictionary i.e. the length of the value for a key.
After looking up the help('dict'), I could only find the function to return number of keys i.e. dict.__len__().
I tried the Java method(hoping that it could work) i.e. len(dict.items()[0]) but it evaluated to 2.
I intend to find this:
Length of value for first key: 4
Length of value for second key: 3
when the lists are a part of the dictionary and not as individual lists in case their length is len(list).
Any suggestions will be of great help.
dict.items() is a list containing all key/value-tuples of the dictionary, e.g.:
[(1, [1,2,3,4]), (2, [5,6,7])]
So if you write len(dict.items()[0]), then you ask for the length of the first tuple of that items-list. Since the tuples of dictionaries are always 2-tuples (pairs), you get the length 2. If you want the length of a value for a given key, then write:
len(dict[key])
Aso: Try not to use the names of standard types (like str, dict, set etc.) as variable names. Python does not complain, but it hides the type names and may result in unexpected behaviour.
You can do this using a dict comprehension, for example:
>>> var1 = [1,2,3,4]
>>> var2 = [5,6,7]
>>> d = {1:var1, 2:var2}
>>> lengths = {key:len(value) for key,value in d.iteritems()}
>>> lengths
{1: 4, 2: 3}
Your "Java" method would also nearly have worked, by the way (but is rather unpythonic). You just used the wrong index:
>>> d.items()
[(1, [1, 2, 3, 4]), (2, [5, 6, 7])]
>>> d.items()[0]
(1, [1, 2, 3, 4])
>>> len(d.items()[0][1])
4
>>>for k,v in dict.iteritems():
k,len(v)
ans:-
(1, 4)
(2, 3)
or
>>>var1=[1,2,3,4]
>>>var2=[5,6,7]
>>>dict={1:var1,2:var2}
ans:-
>>>[len(v) for k,v in dict.iteritems()]
[4, 3]

Flatten a dictionary of dictionaries (2 levels deep) of lists

I'm trying to wrap my brain around this but it's not flexible enough.
In my Python script I have a dictionary of dictionaries of lists. (Actually it gets a little deeper but that level is not involved in this question.) I want to flatten all this into one long list, throwing away all the dictionary keys.
Thus I want to transform
{1: {'a': [1, 2, 3], 'b': [0]},
2: {'c': [4, 5, 1], 'd': [3, 8]}}
to
[1, 2, 3, 0, 4, 5, 1, 3, 8]
I could probably set up a map-reduce to iterate over items of the outer dictionary to build a sublist from each subdictionary and then concatenate all the sublists together.
But that seems inefficient for large data sets, because of the intermediate data structures (sublists) that will get thrown away. Is there a way to do it in one pass?
Barring that, I would be happy to accept a two-level implementation that works... my map-reduce is rusty!
Update:
For those who are interested, below is the code I ended up using.
Note that although I asked above for a list as output, what I really needed was a sorted list; i.e. the output of the flattening could be any iterable that can be sorted.
def genSessions(d):
"""Given the ipDict, return an iterator that provides all the sessions,
one by one, converted to tuples."""
for uaDict in d.itervalues():
for sessions in uaDict.itervalues():
for session in sessions:
yield tuple(session)
...
# Flatten dict of dicts of lists of sessions into a list of sessions.
# Sort that list by start time
sessionsByStartTime = sorted(genSessions(ipDict), key=operator.itemgetter(0))
# Then make another copy sorted by end time.
sessionsByEndTime = sorted(sessionsByStartTime, key=operator.itemgetter(1))
Thanks again to all who helped.
[Update: replaced nthGetter() with operator.itemgetter(), thanks to #intuited.]
I hope you realize that any order you see in a dict is accidental -- it's there only because, when shown on screen, some order has to be picked, but there's absolutely no guarantee.
Net of ordering issues among the various sublists getting catenated,
[x for d in thedict.itervalues()
for alist in d.itervalues()
for x in alist]
does what you want without any inefficiency nor intermediate lists.
edit: re-read the original question and reworked answer to assume that all non-dictionaries are lists to be flattened.
In cases where you're not sure how far down the dictionaries go, you would want to use a recursive function. #Arrieta has already posted a function that recursively builds a list of non-dictionary values.
This one is a generator that yields successive non-dictionary values in the dictionary tree:
def flatten(d):
"""Recursively flatten dictionary values in `d`.
>>> hat = {'cat': ['images/cat-in-the-hat.png'],
... 'fish': {'colours': {'red': [0xFF0000], 'blue': [0x0000FF]},
... 'numbers': {'one': [1], 'two': [2]}},
... 'food': {'eggs': {'green': [0x00FF00]},
... 'ham': ['lean', 'medium', 'fat']}}
>>> set_of_values = set(flatten(hat))
>>> sorted(set_of_values)
[1, 2, 255, 65280, 16711680, 'fat', 'images/cat-in-the-hat.png', 'lean', 'medium']
"""
try:
for v in d.itervalues():
for nested_v in flatten(v):
yield nested_v
except AttributeError:
for list_v in d:
yield list_v
The doctest passes the resulting iterator to the set function. This is likely to be what you want, since, as Mr. Martelli points out, there's no intrinsic order to the values of a dictionary, and therefore no reason to keep track of the order in which they were found.
You may want to keep track of the number of occurrences of each value; this information will be lost if you pass the iterator to set. If you want to track that, just pass the result of flatten(hat) to some other function instead of set. Under Python 2.7, that other function could be collections.Counter. For compatibility with less-evolved pythons, you can write your own function or (with some loss of efficiency) combine sorted with itertools.groupby.
A recursive function may work:
def flat(d, out=[]):
for val in d.values():
if isinstance(val, dict):
flat(d, out)
else:
out+= val
If you try it with :
>>> d = {1: {'a': [1, 2, 3], 'b': [0]}, 2: {'c': [4, 5, 6], 'd': [3, 8]}}
>>> out = []
>>> flat(d, out)
>>> print out
[1, 2, 3, 0, 4, 5, 6, 3, 8]
Notice that dictionaries have no order, so the list is in random order.
You can also return out (at the end of the loop) and don't call the function with a list argument.
def flat(d, out=[]):
for val in d.values():
if isinstance(val, dict):
flat(d, out)
else:
out+= val
return out
call as:
my_list = flat(d)

Categories