This question already has answers here:
Accessing dict_keys element by index in Python3
(7 answers)
Closed 2 years ago.
I have this sentence:
def Ciudad(prob):
numero = random.random()
ciudad = prob.keys()[0]
for i in prob.keys():
if(numero > prob[i]):
if(prob[i] > prob[ciudad]):
ciudad = i
else:
if(prob[i] > prob[ciudad]):
ciudad = i
return ciudad
But when I call it this error pops:
TypeError: 'dict_keys' object does not support indexing
is it a version problem? I'm using Python 3.3.2
dict.keys() is a dictionary view. Just use list() directly on the dictionary instead if you need a list of keys, item 0 will be the first key in the (arbitrary) dictionary order:
list(prob)[0]
or better still just use:
next(iter(dict))
Either method works in both Python 2 and 3 and the next() option is certainly more efficient for Python 2 than using dict.keys(). Note however that dictionaries have no set order and you will not know what key will be listed first.
It looks as if you are trying to find the maximum key instead, use max() with dict.get:
def Ciudad(prob):
return max(prob, key=prob.get)
The function result is certainly going to be the same for any given prob dictionary, as your code doesn't differ in codepaths between the random number comparison branches of the if statement.
In Python 3.x, dict.keys() does not return a list, it returns an iterable (specifically, a dictionary view). It is worth noting that dict itself is also an iterable of the keys.
If you want to obtain the first key, use next(iter(dict)) instead. (Note that before Python 3.6 dictionaries were unordered, so the 'first' element was an arbitrary one. Since 3.6 it will be based on insertion order. If you need that behaviour in older versions or with cross-version compatibility, you can use collections.OrderedDict).
This works quite simply: we take the iterable from the dictionary view with iter(), then use next() to advance it by one and get the first key.
If you need to iterate over the keys—then there is definitely no need to construct a list:
for key in dict:
...
These are all advantageous when compared to using list() as it means a list isn't constructed - making it faster and more memory efficient (hence why the default behaviour of keys() was changed in 3.x). Even in Python 2.x you would be better off doing next(iter(dict.iterkeys()).
Note all these things apply to dict.values() and dict.items() as well.
I've had success turning the iterables taken from a dictionary into a list.
So, for dic.keys(), dic.values(), and dic.items(), in Python3.6, you can:
dic = {'a':3, 'b':2, 'c':3}
print(dic)
dictkeys = dic.keys() # or values/items
print(dictkeys)
keylist = []
keylist.extend(iter(dictkeys)) # my big revelation
print('keylist', keylist)
Related
Say I have a dictionary and then I have a list that contains the dictionary's keys. Is there a way to sort the list based off of the dictionaries values?
I have been trying this:
trial_dict = {'*':4, '-':2, '+':3, '/':5}
trial_list = ['-','-','+','/','+','-','*']
I went to use:
sorted(trial_list, key=trial_dict.values())
And got:
TypeError: 'list' object is not callable
Then I went to go create a function that could be called with trial_dict.get():
def sort_help(x):
if isinstance(x, dict):
for i in x:
return x[i]
sorted(trial_list, key=trial_dict.get(sort_help(trial_dict)))
I don't think the sort_help function is having any affect on the sort though. I'm not sure if using trial_dict.get() is the correct way to go about this either.
Yes dict.get is the correct (or at least, the simplest) way:
sorted(trial_list, key=trial_dict.get)
As Mark Amery commented, the equivalent explicit lambda:
sorted(trial_list, key=lambda x: trial_dict[x])
might be better, for at least two reasons:
the sort expression is visible and immediately editable
it doesn't suppress errors (when the list contains something that is not in the dict).
The key argument in the sorted builtin function (or the sort method of lists) has to be a function that maps members of the list you're sorting to the values you want to sort by. So you want this:
sorted(trial_list, key=lambda x: trial_dict[x])
I am trying to define a series of dictionaries and then iterate through them below. I've tried putting the dictionary names into a list to iterate over, but that then throws up an error that a string does not have .keys() method. I'm presuming that is because Python thinks the values in the list are just strings and not meant to represent the dictionaries above.
I'm not sure how else I could code this though. The code is here:
prem_year_map = {
2011: 2935,
2012: 3389,
2013: 3853,
2014: 4311,
}
year_tournament_map = {
2013: 8273,
2012: 6978,
2011: 5861,
2010: 4940,
}
tournament_list = [prem_year_map, year_tournament_map]
for x in tournament_list:
years = sorted(tournament_list.keys())
print years
Can anyone suggest an alternative method?
Thanks
I'm presuming that is because Python thinks the values in the list are just strings and not meant to represent the dictionaries above.
This is not right. A list in Python can contain any type of reference.
You simply need to use the object.keys() instead of tournament_list.keys() (the latter you are asking for keys of the list, which do not exist - the dictionaries have the keys)
for x in tournament_list:
years = sorted(x.keys())
print years
As pointed out by #JonClements you can also used sorted(x) which returns a list (and is a bit more efficient in Python 2.x). Note that it can't return a dictionary since the standard dictionary cannot preserve an order.
To iterate dictionary key and value you need use different iterator.
for key, value in {}.iteritems():
print key, value
The best choice is standard itertools.
for key, value in itertools.chain(dict1.iteritems(), dict2.iteritems())
print key, value
You can also do list of iterators and iterate them.
iterators = []
iterators.append(oneDict.iteritems())
for iterator in iterators:
for item in iterator:
yield item # (key, value)
Choose what is the simplest.
It should be:
for x in tournament_list:
years = sorted(x.keys())
print years
Otherwise you are trying to get the keys from the list of dictionaries (which of course make no sense).
This question already has answers here:
Iterating over dictionaries using 'for' loops
(15 answers)
Closed 8 years ago.
Please see below code snippet for join method (used Python 2.7.2):
iDict={'1_key':'abcd','2_key':'ABCD','3_key':'bcde','4_key':'BCDE'}
'--'.join(iDict)
Result shown as
'2_key--1_key--4_key--3_key'
Please comment why only keys are joined? Also the sequence is not in order.
Note - below are the individual methods.
'--'.join(iDict.values()) ==> 'ABCD--abcd--BCDE--bcde' ==> the sequence is not in order
'--'.join(iDict.keys()) ==> '2_key--1_key--4_key--3_key' ==> the sequence is not in orde
If you see the docs, you learn that iterating over dict returns keys.
You need to iterate over dict.items(), that it over tuples (key, value):
'--'.join(iDict.items())
If you need to have key AND value joined in one string, you need to explicitly tell Python how to do this:
'--'.join('{} : {}'.format(key, value) for key, value in iDict.items())
Python dictionaries are unordered (or rather, their order is arbitrary), and when you iterate on them, only the keys are returned:
>>> d = {'0':0, '1':1, '2':2, '3':3, '4':4}
>>> print(d)
{'4': 4, '1': 1, '0': 0, '3': 3, '2': 2}
If you need both keys and values, use iDict.items().
If you need ordering, use collections.OrderedDict.
Iteration over a dictionary only ever yields keys:
>>> list(iDict)
['2_key', '1_key', '4_key', '3_key']
See the dict() documentation:
iter(d)
Return an iterator over the keys of the dictionary. This is a shortcut for iterkeys().
Both list() and str.join() will call iter() on their arguments to iterate over the elements.
Dictionaries are unordered containers; their order stems from the underlying data structure and depends on the insertion and deletion history of the keys.
This is documented under dict.items():
CPython implementation detail: Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.
Also see Why is the order in dictionaries and sets arbitrary?
Given a python dictionary and an integer n, I need to access the nth key. I need to do this repeatedly many times in my project.
I have written a function which does this:
def ix(self,dict,n):
count=0
for i in sorted(dict.keys()):
if n==count:
return i
else:
count+=1
But the problem is that if the dictionary is huge, the time complexity increases when used repeatedly.
Is there an efficient way to do this?
I guess you wanted to do something like this, but as dictionary don't have any order so the order of keys in dict.keys can be anything:
def ix(self, dct, n): #don't use dict as a variable name
try:
return list(dct)[n] # or sorted(dct)[n] if you want the keys to be sorted
except IndexError:
print 'not enough keys'
dict.keys() returns a list so, all you need to do is dict.keys()[n]
But, a dictionary is an unordered collection so nth element does not make any sense in this context.
Note: Indexing dict.keys() is not supported in python3
For those that want to avoid the creation of a new temporary list just to access the nth element, I suggest to use an iterator.
from itertools import islice
def nth_key(dct, n):
it = iter(dct)
# Consume n elements.
next(islice(it, n, n), None)
# Return the value at the current position.
# This raises StopIteration if n is beyond the limits.
# Use next(it, None) to suppress that exception.
return next(it)
This can be notably faster for very large dictionaries compared to converting the keys into a temporary list first and then accessing its nth element.
It is mentioned in multiple answers, that dictionaries were unordered. This is nonly true for python versions up to 3.6. From 3.7 ongoing, dictionaries are in fact ordered.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inverse dictionary lookup - Python
reverse mapping of dictionary with Python
How do i get key of index in dictionary?
For example like:
i = {'a': 0, 'b': 1, 'c': 2}
so if i want to get key of i[0], it will return 'a'
You could do something like this:
i={'foo':'bar', 'baz':'huh?'}
keys=i.keys() #in python 3, you'll need `list(i.keys())`
values=i.values()
print keys[values.index("bar")] #'foo'
However, any time you change your dictionary, you'll need to update your keys,values because dictionaries are not ordered in versions of Python prior to 3.7. In these versions, any time you insert a new key/value pair, the order you thought you had goes away and is replaced by a new (more or less random) order. Therefore, asking for the index in a dictionary doesn't make sense.
As of Python 3.6, for the CPython implementation of Python, dictionaries remember the order of items inserted. As of Python 3.7+ dictionaries are ordered by order of insertion.
Also note that what you're asking is probably not what you actually want. There is no guarantee that the inverse mapping in a dictionary is unique. In other words, you could have the following dictionary:
d={'i':1, 'j':1}
In that case, it is impossible to know whether you want i or j and in fact no answer here will be able to tell you which ('i' or 'j') will be picked (again, because dictionaries are unordered). What do you want to happen in that situation? You could get a list of acceptable keys ... but I'm guessing your fundamental understanding of dictionaries isn't quite right.
Python dictionaries have a key and a value, what you are asking for is what key(s) point to a given value.
You can only do this in a loop:
[k for (k, v) in i.iteritems() if v == 0]
Note that there can be more than one key per value in a dict; {'a': 0, 'b': 0} is perfectly legal.
If you want ordering you either need to use a list or a OrderedDict instance instead:
items = ['a', 'b', 'c']
items.index('a') # gives 0
items[0] # gives 'a'
By definition dictionaries are unordered, and therefore cannot be indexed. For that kind of functionality use an ordered dictionary. Python Ordered Dictionary