Why am I getting the wrong values? - python-3.x

player_list= {'peter':0, 'karel':0}
naam = input("Welke speler moet een score + 1 krijgen?")
for key, value in player_list.items():
player_list[naam] = value + 1
print(player_list)
Can someone explain me I why get the correct value whenever I enter "peter" but not when I enter "karel"?

I assume, that you'd like to increment dict value of the key which is same as the string that user provides via input. Ask yourself, do you really need to iterate over dict items to do such thing? Dict is key-value structure, and you can access value of the key whenever you provide this key directly.
>>> player_list = {'peter':0, 'karel':0}
>>> player_list['peter']
0
Setting value to the existing dict key is easy. All you need to do is:
>>> player_list['peter'] = 3
>>> player_list['peter']
3
If you'd like to increment value for 'peter' you need to take whatever is stored under 'peter' and add one, but there is no need to iterate over dict items to do that. Like with any other variable, dict element is kind of placeholder for some space of memory that you can access via that placeholder. So in case of any variable you'd do something as:
>>> x = 1
>>> x = x + 1 # or x += 1 for short
...and in case of dict element, you can do the same:
>>> player_list['peter'] = player_list['peter'] + 1 # or:
>>> player_list['peter'] += 1
If you're curious why your current code doesn't work as you expected, run your code using debugger or just add print function:
for key, value in player_list.items():
print("Current key: {}, current value: {}".format(key, value))
player_list[naam] = value + 1
In fact, it's always good to use some debugging tools whenever you don't know why your code execution is different than your expected result.

Related

Pop element at the beginning or at the last from dict in python3

Collection module in python has a datatype OrderedDict(), which enables us to save the key value pairs in the same order as they were inserted in dict. It has a method popitem, which allows us to pop items at the beginning or at the last
dict.popitem(last = True)
dict.popitem(last = False)
The default dict in python 3 also works as OrderedDict(), i.e., it maintains the order of key value pairs as they were inserted. But how to remove the first or the last element from this dict as in OrderedDict(), without using the traditional for loop for accessing the key value pair as
for key, value in dict:
dict.pop(key)
break
I just want to know if there is any inbuild function for popping the first or the last element in default dict of python 3 as in OrderedDict(). I searched but couldn't find any.
Since Python 3.6, dict.popitem always acts as a LIFO like OrderedDict.popitem(last=True) does.
But while there is no direct support from dict to make the popitem method pop from the front of the dict, you can simulate the FIFO behavior of OrderedDict.popitem(last=False) such as:
d = OrderedDict(a=1, b=2)
k, v = d.popitem(last=False) # k = 'a', v = 1
by getting the first key of the dict and then popping that key for its value:
d = {'a': 1, 'b': 2}
k = next(iter(d)) # k = 'a'
v = d.pop(k) # v = 1

sum the values of dictionary only if the keys is equal or greater than x

Given a dictionary which contains keys and values, and I want sum the values based on the keys value. For example, {1:10, 2:20, 3:30, 4:40, 5:50, 6:60}, and sum the values only if is equal or greater than 2 in keys, which output is 200.
x =2
count = 0
for key, value in dictionary.items():
while key == x:
count += 1[value]
And my output is none, and I don't know what I am missing on.
Try this. Your way of iterating over the dictionary items is correct, but inside the loop, you need to check if the current key is greater than or equal to your required key. Only then you should increment the count with the value corresponding to that key which can be retrieved in this way - dictionary[key] or you can simply add the value like count+=value
dictionary = {1:10, 2:20, 3:30, 4:40, 5:50, 6:60}
x=2
count = 0
for key,value in dictionary.items():
if key>=x:
count += dictionary[key]
print(count)
your code is incomplete and won't run as-is, so it's difficult to speculate why you're getting an output of None.
in your requirements you mention "equal or greater than 2" but your code has "key == x". This should be "key >= x".
inside your for loop you have a while. Fixing other issues this would result in an infinite loop. You want an if, not a while.
fixing those things and making an assumption or two, your code would be:
x = 2
count = 0
for key, value in dictionary.items():
if key >= x:
count += value
Alternately, you could write it in a single line of code:
sum ( v for k, v in dictionary.items() if k >= x )
I believe you just need to do as below:
count = 0
for key, value in dictionary.items():
if key >= n:
count += value

List Index Error - Combining list elements via index

'Original String = 1234 A 56 78 90 B'
def func_1(one_dict):
global ends
ends = []
for x in original_string:
if x in one_dict:
ends.append(one_dict[x])
return ends
The above returns:
['B', 'A']
My next function is supposed to then combine them into 1 string and get value from dictionary. I've tried this with/without the str in mult_ends with the same result.
def func_2(two_dict):
global mult_ends
mult_ends = str(ends[0] + ends[1])
for key in mult_ends:
if key in two_dict:
return two_dict[key]
The results confuse me since I use pretty identical processes in other functions with no issue.
IndexError: list index out of range
Why would the list index be out of range when there is clearly a 0 and 1? I've also added global ends to func_2 and I still received the same error.
*** RESTRUCTURED FUNCTIONS INTO 1 ***
def func_1(one_dict):
global ends
ends = []
for x in original_string:
if x in one_dict:
ends.append(one_dict[x])
mult_ends = ends[0] + ends[1]
for key in two_dict:
if key in mult_ends:
return ends_final_dict[key]
return None
Now, it actually does what I want it to do and returns the correct dictionary key in the event log:
A B
However, it does not return when I try to insert it back into my GUI for the user and it still throws the IndexError: list index out of range.

How to predict key from its value in python? [duplicate]

I made a function which will look up ages in a Dictionary and show the matching name:
dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
for age in dictionary.values():
if age == search_age:
name = dictionary[age]
print name
I know how to compare and find the age I just don't know how to show the name of the person. Additionally, I am getting a KeyError because of line 5. I know it's not correct but I can't figure out how to make it search backwards.
mydict = {'george': 16, 'amber': 19}
print mydict.keys()[mydict.values().index(16)] # Prints george
Or in Python 3.x:
mydict = {'george': 16, 'amber': 19}
print(list(mydict.keys())[list(mydict.values()).index(16)]) # Prints george
Basically, it separates the dictionary's values in a list, finds the position of the value you have, and gets the key at that position.
More about keys() and .values() in Python 3: How can I get list of values from dict?
There is none. dict is not intended to be used this way.
dictionary = {'george': 16, 'amber': 19}
search_age = input("Provide age")
for name, age in dictionary.items(): # for name, age in dictionary.iteritems(): (for Python 2.x)
if age == search_age:
print(name)
If you want both the name and the age, you should be using .items() which gives you key (key, value) tuples:
for name, age in mydict.items():
if age == search_age:
print name
You can unpack the tuple into two separate variables right in the for loop, then match the age.
You should also consider reversing the dictionary if you're generally going to be looking up by age, and no two people have the same age:
{16: 'george', 19: 'amber'}
so you can look up the name for an age by just doing
mydict[search_age]
I've been calling it mydict instead of list because list is the name of a built-in type, and you shouldn't use that name for anything else.
You can even get a list of all people with a given age in one line:
[name for name, age in mydict.items() if age == search_age]
or if there is only one person with each age:
next((name for name, age in mydict.items() if age == search_age), None)
which will just give you None if there isn't anyone with that age.
Finally, if the dict is long and you're on Python 2, you should consider using .iteritems() instead of .items() as Cat Plus Plus did in his answer, since it doesn't need to make a copy of the list.
I thought it would be interesting to point out which methods are the quickest, and in what scenario:
Here's some tests I ran (on a 2012 MacBook Pro)
def method1(dict, search_age):
for name, age in dict.iteritems():
if age == search_age:
return name
def method2(dict, search_age):
return [name for name,age in dict.iteritems() if age == search_age]
def method3(dict, search_age):
return dict.keys()[dict.values().index(search_age)]
Results from profile.run() on each method 100,000 times:
Method 1:
>>> profile.run("for i in range(0,100000): method1(dict, 16)")
200004 function calls in 1.173 seconds
Method 2:
>>> profile.run("for i in range(0,100000): method2(dict, 16)")
200004 function calls in 1.222 seconds
Method 3:
>>> profile.run("for i in range(0,100000): method3(dict, 16)")
400004 function calls in 2.125 seconds
So this shows that for a small dict, method 1 is the quickest. This is most likely because it returns the first match, as opposed to all of the matches like method 2 (see note below).
Interestingly, performing the same tests on a dict I have with 2700 entries, I get quite different results (this time run 10,000 times):
Method 1:
>>> profile.run("for i in range(0,10000): method1(UIC_CRS,'7088380')")
20004 function calls in 2.928 seconds
Method 2:
>>> profile.run("for i in range(0,10000): method2(UIC_CRS,'7088380')")
20004 function calls in 3.872 seconds
Method 3:
>>> profile.run("for i in range(0,10000): method3(UIC_CRS,'7088380')")
40004 function calls in 1.176 seconds
So here, method 3 is much faster. Just goes to show the size of your dict will affect which method you choose.
Notes:
Method 2 returns a list of all names, whereas methods 1 and 3 return only the first match.
I have not considered memory usage. I'm not sure if method 3 creates 2 extra lists (keys() and values()) and stores them in memory.
one line version: (i is an old dictionary, p is a reversed dictionary)
explanation : i.keys() and i.values() returns two lists with keys and values of the dictionary respectively. The zip function has the ability to tie together lists to produce a dictionary.
p = dict(zip(i.values(),i.keys()))
Warning : This will work only if the values are hashable and unique.
I found this answer very effective but not very easy to read for me.
To make it more clear you can invert the key and the value of a dictionary. This is make the keys values and the values keys, as seen here.
mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.iteritems())
print(res[16]) # Prints george
or for Python 3, (thanks #kkgarg)
mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.items())
print(res[16]) # Prints george
Also
print(res.get(16)) # Prints george
which is essentially the same that this other answer.
a = {'a':1,'b':2,'c':3}
{v:k for k, v in a.items()}[1]
or better
{k:v for k, v in a.items() if v == 1}
key = next((k for k in my_dict if my_dict[k] == val), None)
Try this one-liner to reverse a dictionary:
reversed_dictionary = dict(map(reversed, dictionary.items()))
If you want to find the key by the value, you can use a dictionary comprehension to create a lookup dictionary and then use that to find the key from the value.
lookup = {value: key for key, value in self.data}
lookup[value]
we can get the Key of dict by :
def getKey(dct,value):
return [key for key in dct if (dct[key] == value)]
You can get key by using dict.keys(), dict.values() and list.index() methods, see code samples below:
names_dict = {'george':16,'amber':19}
search_age = int(raw_input("Provide age"))
key = names_dict.keys()[names_dict.values().index(search_age)]
Here is my take on this problem. :)
I have just started learning Python, so I call this:
"The Understandable for beginners" solution.
#Code without comments.
list1 = {'george':16,'amber':19, 'Garry':19}
search_age = raw_input("Provide age: ")
print
search_age = int(search_age)
listByAge = {}
for name, age in list1.items():
if age == search_age:
age = str(age)
results = name + " " +age
print results
age2 = int(age)
listByAge[name] = listByAge.get(name,0)+age2
print
print listByAge
.
#Code with comments.
#I've added another name with the same age to the list.
list1 = {'george':16,'amber':19, 'Garry':19}
#Original code.
search_age = raw_input("Provide age: ")
print
#Because raw_input gives a string, we need to convert it to int,
#so we can search the dictionary list with it.
search_age = int(search_age)
#Here we define another empty dictionary, to store the results in a more
#permanent way.
listByAge = {}
#We use double variable iteration, so we get both the name and age
#on each run of the loop.
for name, age in list1.items():
#Here we check if the User Defined age = the age parameter
#for this run of the loop.
if age == search_age:
#Here we convert Age back to string, because we will concatenate it
#with the person's name.
age = str(age)
#Here we concatenate.
results = name + " " +age
#If you want just the names and ages displayed you can delete
#the code after "print results". If you want them stored, don't...
print results
#Here we create a second variable that uses the value of
#the age for the current person in the list.
#For example if "Anna" is "10", age2 = 10,
#integer value which we can use in addition.
age2 = int(age)
#Here we use the method that checks or creates values in dictionaries.
#We create a new entry for each name that matches the User Defined Age
#with default value of 0, and then we add the value from age2.
listByAge[name] = listByAge.get(name,0)+age2
#Here we print the new dictionary with the users with User Defined Age.
print
print listByAge
.
#Results
Running: *\test.py (Thu Jun 06 05:10:02 2013)
Provide age: 19
amber 19
Garry 19
{'amber': 19, 'Garry': 19}
Execution Successful!
get_key = lambda v, d: next(k for k in d if d[k] is v)
Consider using Pandas. As stated in William McKinney's "Python for Data Analysis'
Another way to think about a Series is as a fixed-length, ordered
dict, as it is a mapping of index values to data values. It can be
used in many contexts where you might use a dict.
import pandas as pd
list = {'george':16,'amber':19}
lookup_list = pd.Series(list)
To query your series do the following:
lookup_list[lookup_list.values == 19]
Which yields:
Out[1]:
amber 19
dtype: int64
If you need to do anything else with the output transforming the
answer into a list might be useful:
answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)
d= {'george':16,'amber':19}
dict((v,k) for k,v in d.items()).get(16)
The output is as follows:
-> prints george
Here, recover_key takes dictionary and value to find in dictionary. We then loop over the keys in dictionary and make a comparison with that of value and return that particular key.
def recover_key(dicty,value):
for a_key in dicty.keys():
if (dicty[a_key] == value):
return a_key
One line solution using list comprehension, which returns multiple keys if the value is possibly present multiple times.
[key for key,value in mydict.items() if value == 16]
for name in mydict:
if mydict[name] == search_age:
print(name)
#or do something else with it.
#if in a function append to a temporary list,
#then after the loop return the list
my_dict = {'A': 19, 'B': 28, 'carson': 28}
search_age = 28
take only one
name = next((name for name, age in my_dict.items() if age == search_age), None)
print(name) # 'B'
get multiple data
name_list = [name for name, age in filter(lambda item: item[1] == search_age, my_dict.items())]
print(name_list) # ['B', 'carson']
I glimpsed all answers and none mentioned simply using list comprehension?
This Pythonic one-line solution can return all keys for any number of given values (tested in Python 3.9.1):
>>> dictionary = {'george' : 16, 'amber' : 19, 'frank': 19}
>>>
>>> age = 19
>>> name = [k for k in dictionary.keys() if dictionary[k] == age]; name
['george', 'frank']
>>>
>>> age = (16, 19)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
['george', 'amber', 'frank']
>>>
>>> age = (22, 25)
>>> name = [k for k in dictionary.keys() if dictionary[k] in age]; name
[]
it's answered, but it could be done with a fancy 'map/reduce' use, e.g.:
def find_key(value, dictionary):
return reduce(lambda x, y: x if x is not None else y,
map(lambda x: x[0] if x[1] == value else None,
dictionary.iteritems()))
I tried to read as many solutions as I can to prevent giving duplicate answer. However, if you are working on a dictionary which values are contained in lists and if you want to get keys that have a particular element you could do this:
d = {'Adams': [18, 29, 30],
'Allen': [9, 27],
'Anderson': [24, 26],
'Bailey': [7, 30],
'Baker': [31, 7, 10, 19],
'Barnes': [22, 31, 10, 21],
'Bell': [2, 24, 17, 26]}
Now lets find names that have 24 in their values.
for key in d.keys():
if 24 in d[key]:
print(key)
This would work with multiple values as well.
Just my answer in lambda and filter.
filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age , dictionary )
already been answered, but since several people mentioned reversing the dictionary, here's how you do it in one line (assuming 1:1 mapping) and some various perf data:
python 2.6:
reversedict = dict([(value, key) for key, value in mydict.iteritems()])
2.7+:
reversedict = {value:key for key, value in mydict.iteritems()}
if you think it's not 1:1, you can still create a reasonable reverse mapping with a couple lines:
reversedict = defaultdict(list)
[reversedict[value].append(key) for key, value in mydict.iteritems()]
how slow is this: slower than a simple search, but not nearly as slow as you'd think - on a 'straight' 100000 entry dictionary, a 'fast' search (i.e. looking for a value that should be early in the keys) was about 10x faster than reversing the entire dictionary, and a 'slow' search (towards the end) about 4-5x faster. So after at most about 10 lookups, it's paid for itself.
the second version (with lists per item) takes about 2.5x as long as the simple version.
largedict = dict((x,x) for x in range(100000))
# Should be slow, has to search 90000 entries before it finds it
In [26]: %timeit largedict.keys()[largedict.values().index(90000)]
100 loops, best of 3: 4.81 ms per loop
# Should be fast, has to only search 9 entries to find it.
In [27]: %timeit largedict.keys()[largedict.values().index(9)]
100 loops, best of 3: 2.94 ms per loop
# How about using iterkeys() instead of keys()?
# These are faster, because you don't have to create the entire keys array.
# You DO have to create the entire values array - more on that later.
In [31]: %timeit islice(largedict.iterkeys(), largedict.values().index(90000))
100 loops, best of 3: 3.38 ms per loop
In [32]: %timeit islice(largedict.iterkeys(), largedict.values().index(9))
1000 loops, best of 3: 1.48 ms per loop
In [24]: %timeit reversedict = dict([(value, key) for key, value in largedict.iteritems()])
10 loops, best of 3: 22.9 ms per loop
In [23]: %%timeit
....: reversedict = defaultdict(list)
....: [reversedict[value].append(key) for key, value in largedict.iteritems()]
....:
10 loops, best of 3: 53.6 ms per loop
Also had some interesting results with ifilter. Theoretically, ifilter should be faster, in that we can use itervalues() and possibly not have to create/go through the entire values list. In practice, the results were... odd...
In [72]: %%timeit
....: myf = ifilter(lambda x: x[1] == 90000, largedict.iteritems())
....: myf.next()[0]
....:
100 loops, best of 3: 15.1 ms per loop
In [73]: %%timeit
....: myf = ifilter(lambda x: x[1] == 9, largedict.iteritems())
....: myf.next()[0]
....:
100000 loops, best of 3: 2.36 us per loop
So, for small offsets, it was dramatically faster than any previous version (2.36 *u*S vs. a minimum of 1.48 *m*S for previous cases). However, for large offsets near the end of the list, it was dramatically slower (15.1ms vs. the same 1.48mS). The small savings at the low end is not worth the cost at the high end, imho.
Cat Plus Plus mentioned that this isn't how a dictionary is intended to be used. Here's why:
The definition of a dictionary is analogous to that of a mapping in mathematics. In this case, a dict is a mapping of K (the set of keys) to V (the values) - but not vice versa. If you dereference a dict, you expect to get exactly one value returned. But, it is perfectly legal for different keys to map onto the same value, e.g.:
d = { k1 : v1, k2 : v2, k3 : v1}
When you look up a key by it's corresponding value, you're essentially inverting the dictionary. But a mapping isn't necessarily invertible! In this example, asking for the key corresponding to v1 could yield k1 or k3. Should you return both? Just the first one found? That's why indexof() is undefined for dictionaries.
If you know your data, you could do this. But an API can't assume that an arbitrary dictionary is invertible, hence the lack of such an operation.
here is my take on it. This is good for displaying multiple results just in case you need one. So I added the list as well
myList = {'george':16,'amber':19, 'rachel':19,
'david':15 } #Setting the dictionary
result=[] #Making ready of the result list
search_age = int(input('Enter age '))
for keywords in myList.keys():
if myList[keywords] ==search_age:
result.append(keywords) #This part, we are making list of results
for res in result: #We are now printing the results
print(res)
And that's it...
There is no easy way to find a key in a list by 'looking up' the value. However, if you know the value, iterating through the keys, you can look up values in the dictionary by the element. If D[element] where D is a dictionary object, is equal to the key you're trying to look up, you can execute some code.
D = {'Ali': 20, 'Marina': 12, 'George':16}
age = int(input('enter age:\t'))
for element in D.keys():
if D[element] == age:
print(element)
You need to use a dictionary and reverse of that dictionary. It means you need another data structure. If you are in python 3, use enum module but if you are using python 2.7 use enum34 which is back ported for python 2.
Example:
from enum import Enum
class Color(Enum):
red = 1
green = 2
blue = 3
>>> print(Color.red)
Color.red
>>> print(repr(Color.red))
<color.red: 1="">
>>> type(Color.red)
<enum 'color'="">
>>> isinstance(Color.green, Color)
True
>>> member = Color.red
>>> member.name
'red'
>>> member.value
1
def get_Value(dic,value):
for name in dic:
if dic[name] == value:
del dic[name]
return name

How do you modify a variable that's a value in a dictionary when calling that variable by its key?

n = 3
d = {'x':n}
d['x'] += 1
print(n)
When I run it, I get
3
How do I make n = 4?
You can't do this, at least, not in any simple way.
The issue is very similar when you're just dealing with two variables bound to the same object. If you rebind one of them with an assignment, you will not see the new value through the other variable:
a = 3
b = a
a += 1 # binds a to a new integer, 4, since integers are immutable
print(b) # prints 3, not 4
One exception is if you are not binding a new value to the variable, but instead modifying a mutable object in-place. For instance, if instead of 1 you has a one-element list [1], you could replace the single value without creating a new list:
a = [3]
b = a
a[0] += 1 # doesn't rebind a, just mutates the list it points to
print(b[0]) # prints 4, since b still points to the same list as a
So, for your dictionary example you could take a similar approach and have n and your dictionary value be a list or other container object that you modify in-place.
Alternatively, you could store the variable name "n" in your dictionary and then rather than replacing it in your other code, you could use for a lookup in the globals dict:
n = 3
d = {"x": "n"} # note, the dictionary value is the string "n", not the variable n's value
globals()[d["x"]] += 1
print(n) # this actually does print 4, as you wanted
This is very awkward, of course, and only works when n is a global variable (you can't use the nominally equivalent call to locals in a function, as modifying the dictionary returned by locals doesn't change the local variables). I would not recommend this approach, but I wanted to show it can be done, if only badly.
You could use a class to contain the data values to enable additions. Basically you are creating a mutable object which acts as an integer.
It is a work around, but lets you accomplish what you want.
Note, that you probably need to override a few more Python operators to get full coverage:
class MyInt(object):
val = 0
def __init__(self,val):
self.val = val
def __iadd__(self,val):
self.val = self.val + val
def __repr__(self):
return repr(self.val)
n = MyInt(3)
print(n)
d = {'x':n}
d['x'] += 1
print(n)

Resources