This will convert the dict_keys object to a list:
Copylist(newdict.keys())
On the other hand, you should ask yourself whether or not it matters. It is Pythonic to assume duck typing -- if it looks like a duck and it quacks like a duck, it is a duck. The dict_keys object can be iterated over just like a list. For instance:
Copyfor key in newdict.keys():
print(key)
Note that dict_keys doesn't support insertion newdict[k] = v, though you may not need it.
How can i retrieve all the values of a key for a list of dictionaries nested in a dictionary
Why can't I use a list as a dict key in python? Exactly what can and cannot be used, and why? - Stack Overflow
How do you add a list as the value of a key inside a dictionary? What about tuples of lists?
python - Convert list into a dictionary - Stack Overflow
Videos
This will convert the dict_keys object to a list:
Copylist(newdict.keys())
On the other hand, you should ask yourself whether or not it matters. It is Pythonic to assume duck typing -- if it looks like a duck and it quacks like a duck, it is a duck. The dict_keys object can be iterated over just like a list. For instance:
Copyfor key in newdict.keys():
print(key)
Note that dict_keys doesn't support insertion newdict[k] = v, though you may not need it.
Python >= 3.5 alternative: unpack into a list literal [*newdict]
New unpacking generalizations (PEP 448) were introduced with Python 3.5 allowing you to now easily do:
Copy>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]
Unpacking with * works with any object that is iterable and, since dictionaries return their keys when iterated through, you can easily create a list by using it within a list literal.
Adding .keys() i.e [*newdict.keys()] might help in making your intent a bit more explicit though it will cost you a function look-up and invocation. (which, in all honesty, isn't something you should really be worried about).
The *iterable syntax is similar to doing list(iterable) and its behaviour was initially documented in the Calls section of the Python Reference manual. With PEP 448 the restriction on where *iterable could appear was loosened allowing it to also be placed in list, set and tuple literals, the reference manual on Expression lists was also updated to state this.
Though equivalent to list(newdict) with the difference that it's faster (at least for small dictionaries) because no function call is actually performed:
Copy%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop
%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop
%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop
with larger dictionaries the speed is pretty much the same (the overhead of iterating through a large collection trumps the small cost of a function call).
In a similar fashion, you can create tuples and sets of dictionary keys:
Copy>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}
beware of the trailing comma in the tuple case!
Let say there is a list inside a dictionary, and in this list there are dictionaries with same keys. So is it possible to get all values for a key inside that list.
I used this 👇
price = dict["data"][:]["price"]
It did'n't worked ofc
Disclamer: I know other ways around(like numpy, def a function, loop etc etc). I just wanna know if it is possible this way.
There's a good article on the topic in the Python wiki: Why Lists Can't Be Dictionary Keys. As explained there:
What would go wrong if Python allowed using lists as keys, say, using their memory location as the hash?
It would cause some unexpected behavior. Lists are generally treated as if their value was derived from their content's values, for instance when checking (in-)equality. Many would - understandably - expect that you can use any list [1, 2] to get the same key, where you'd have to keep around exactly the same list object. But lookup by value breaks as soon as a list used as a key is modified, and lookup by identity requires keeping track of that exact list object - which isn't an ordinary requirement for working with lists.
Other objects, such as modules and object, make a much bigger deal out of their object identity anyway (when was the last time you had two distinct module objects called sys?), and are compared by that anyway. Therefore, it's less surprising - or even expected - that they, when used as dict keys, compare by identity in that case as well.
A list can be converted to a tuple, which can be used as a dict key: e.g.
d = {tuple([1,2,3]): 'value'}
I am trying to add a list, or a tuple of lists, as the value to a key inside a dictionary. I'm starting with a dictionary that has empty lists as values, and then adding to the value of each key inside a loop like this:
dict = {'key1': [], 'key2': [], 'key3': []}
list = ['a', 'b']
for key,value in dict.items():
# dict[key].append(list)
value.append(list)
print(dict)
What is the difference between dict[key].append(list) and value.append(list)? They both produce the same dictionary when the other is commented out.
Further, how would I add a second list to one of these values as a tuple? Something like adding the list ['c', 'd'] to key2, like this:
{'key1': [['a', 'b']], 'key2': [['a', 'b'], ['c', 'd']], 'key3': [['a', 'b']]}Thanks for any replies!
If you are still thinking what the! You would not be alone, its actually not that complicated really, let me explain.
How to turn a list into a dictionary using built-in functions only
We want to turn the following list into a dictionary using the odd entries (counting from 1) as keys mapped to their consecutive even entries.
Copyl = ["a", "b", "c", "d", "e"]
dict()
To create a dictionary we can use the built in dict function for Mapping Types as per the manual the following methods are supported.
Copydict(one=1, two=2)
dict({'one': 1, 'two': 2})
dict(zip(('one', 'two'), (1, 2)))
dict([['two', 2], ['one', 1]])
The last option suggests that we supply a list of lists with 2 values or (key, value) tuples, so we want to turn our sequential list into:
Copyl = [["a", "b"], ["c", "d"], ["e",]]
We are also introduced to the zip function, one of the built-in functions which the manual explains:
returns a list of tuples, where the i-th tuple contains the i-th element from each of the arguments
In other words if we can turn our list into two lists a, c, e and b, d then zip will do the rest.
slice notation
Slicings which we see used with Strings and also further on in the List section which mainly uses the range or short slice notation but this is what the long slice notation looks like and what we can accomplish with step:
Copy>>> l[::2]
['a', 'c', 'e']
>>> l[1::2]
['b', 'd']
>>> zip(['a', 'c', 'e'], ['b', 'd'])
[('a', 'b'), ('c', 'd')]
>>> dict(zip(l[::2], l[1::2]))
{'a': 'b', 'c': 'd'}
Even though this is the simplest way to understand the mechanics involved there is a downside because slices are new list objects each time, as can be seen with this cloning example:
Copy>>> a = [1, 2, 3]
>>> b = a
>>> b
[1, 2, 3]
>>> b is a
True
>>> b = a[:]
>>> b
[1, 2, 3]
>>> b is a
False
Even though b looks like a they are two separate objects now and this is why we prefer to use the grouper recipe instead.
grouper recipe
Although the grouper is explained as part of the itertools module it works perfectly fine with the basic functions too.
Some serious voodoo right? =) But actually nothing more than a bit of syntax sugar for spice, the grouper recipe is accomplished by the following expression.
Copy*[iter(l)]*2
Which more or less translates to two arguments of the same iterator wrapped in a list, if that makes any sense. Lets break it down to help shed some light.
zip for shortest
Copy>>> l*2
['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']
>>> [l]*2
[['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
>>> [iter(l)]*2
[<listiterator object at 0x100486450>, <listiterator object at 0x100486450>]
>>> zip([iter(l)]*2)
[(<listiterator object at 0x1004865d0>,),(<listiterator object at 0x1004865d0>,)]
>>> zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd')]
>>> dict(zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd'}
As you can see the addresses for the two iterators remain the same so we are working with the same iterator which zip then first gets a key from and then a value and a key and a value every time stepping the same iterator to accomplish what we did with the slices much more productively.
You would accomplish very much the same with the following which carries a smaller What the? factor perhaps.
Copy>>> it = iter(l)
>>> dict(zip(it, it))
{'a': 'b', 'c': 'd'}
What about the empty key e if you've noticed it has been missing from all the examples which is because zip picks the shortest of the two arguments, so what are we to do.
Well one solution might be adding an empty value to odd length lists, you may choose to use append and an if statement which would do the trick, albeit slightly boring, right?
Copy>>> if len(l) % 2:
... l.append("")
>>> l
['a', 'b', 'c', 'd', 'e', '']
>>> dict(zip(*[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': ''}
Now before you shrug away to go type from itertools import izip_longest you may be surprised to know it is not required, we can accomplish the same, even better IMHO, with the built in functions alone.
map for longest
I prefer to use the map() function instead of izip_longest() which not only uses shorter syntax doesn't require an import but it can assign an actual None empty value when required, automagically.
Copy>>> l = ["a", "b", "c", "d", "e"]
>>> l
['a', 'b', 'c', 'd', 'e']
>>> dict(map(None, *[iter(l)]*2))
{'a': 'b', 'c': 'd', 'e': None}
Comparing performance of the two methods, as pointed out by KursedMetal, it is clear that the itertools module far outperforms the map function on large volumes, as a benchmark against 10 million records show.
Copy$ time python -c 'dict(map(None, *[iter(range(10000000))]*2))'
real 0m3.755s
user 0m2.815s
sys 0m0.869s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(10000000))]*2, fillvalue=None))'
real 0m2.102s
user 0m1.451s
sys 0m0.539s
However the cost of importing the module has its toll on smaller datasets with map returning much quicker up to around 100 thousand records when they start arriving head to head.
Copy$ time python -c 'dict(map(None, *[iter(range(100))]*2))'
real 0m0.046s
user 0m0.029s
sys 0m0.015s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100))]*2, fillvalue=None))'
real 0m0.067s
user 0m0.042s
sys 0m0.021s
$ time python -c 'dict(map(None, *[iter(range(100000))]*2))'
real 0m0.074s
user 0m0.050s
sys 0m0.022s
$ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100000))]*2, fillvalue=None))'
real 0m0.075s
user 0m0.047s
sys 0m0.024s
See nothing to it! =)
nJoy!
Using the usual grouper recipe, you could do:
Python 2:
Copyd = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))
Python 3:
Copyd = dict(itertools.zip_longest(*[iter(l)] * 2, fillvalue=""))
The original list I have is:
[['James', '100.00', '90.00', '85.50'], ['Nick', '78.00', '85.00', '80.50'], ['William', '95.50', '92.00', '100.00']]
I want to turn the list into a dictionary that look like this:
{'James': ['100.00', '90.00', '85.50'], 'Nick': ['78.00', '85.00', '80.50'], 'William': ['95.50', '92.00', '100.00']}
I am a beginner of python coding, could anyone please tell me how to get the output for this?