Pop element at the beginning or at the last from dict in python3 - python-3.x

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

Related

Can someone explain the logic behind this code?

a = [1,2,3,4,4,2,2]
d = {k: v for v, k in enumerate(a)}
print(d)
Let me rephrase myself.
from the above code what does this line exactly mean.
{k: v for v, k in enumerate(a)}
First you have enumerate(a). This built-in function adds a counter to an iterable and returns it in a form of enumerating object. So for every element in a, it makes a tuple (index, a[index]), where here: index will increase from 0 to 6.
Then for v, k in enumerate(a): we have already seen what enumerate(a) does, now you tell Python that for each loop, the tuple (index, a[index]) is represented by v, k. So v = index and k = a[index].
Then at last we find {k: v for v, k in enumerate(a)}, the accolades tell that you're making a dictionary. The k: v tells you that every loop, you will take k as a key of your dictionary with v the corresponding value. So the dictionary its keys will exist out of the elements of a, with their corresponding value equaling their indexc in the list a.
Now you have to take in mind that in a dictionary, each key can only exist once. So when the program comes across a key that already exists in the dictionary, it will overwrite it. That is why for example the first '2' with index 1, doesn't show up in the dictionary. Because it gets first overwritten by the '2' with index 5, after which this key and its value get overwritten by the last '2' and its index 6.
#i have added 10 as a last item in your list for easy understanding.
a = [1,2,3,4,4,2,2,10]
d = {k: v for v, k in enumerate(a)} #this is a dictionary comprehension
print(d)
where 'k' returns the items in the list one by one and 'v' returns the count for
each item in list starting from 0.
like k-->v
1-->0
2-->1
3-->2
4-->3
4-->4
2-->5
2-->6
10-->7
The output is {1: 0, 2: 6, 3: 2, 4: 4, 10: 7}
as you know dictionary doesnt allow duplicate keys. when any duplicate key
arrives it rewrites the previous one and holds the latest one.
{1: 0, 2: 6, 3: 2, 4: 4, 10: 7}
as we have 1 in only once in the input list we get 1:0
and for 2 we have three values 1,5,6 as 6 is the latest value. we get
2:6
Like wise happens.

python3 value returned wrong with container variable

I meet a code that failed to meet my expectation. Details as below:
a = ['name']
b = [('name=cheng',),('name=huang',),('name=pan',)]
Dict = {}
c = []
for i in range(0,3):
for j in range(0,1):
Dict[a[j]] = b[i][j]
c.append(Dict)
print(c)
>>> [{'name':'name=pan'},{'name':'name=pan'},{'name':'name=pan'}]
what i expected should be
>>> [{'name':'name=cheng'},{'name':'name=huang'},{'name':'name=pan'}]
So could you please tell me how to solve the issue ?
You are changing the value of Dict in place and not creating a new dictionary every time. Each iteration of the loop, you are setting Dict["name"] equal to one of the elements in b and then appending it to the list. The next iteration of your loop changes dict in place (meaning the previous version you appending to c will also be changed). The result is that your list c is filled with 3 exact copies (exact same location in memory) of the dictionary created in the final iteration of the loop.
How do you fix this? Make a new dictionary every time.
a = ['name']
b = [('name=cheng',),('name=huang',),('name=pan',)]
c = []
for i in range(0,3):
for j in range(0,1):
temp_dict = {a[j]: b[i][j]}
c.append(temp_dict)
print(c)
Result:
[{'name': 'name=cheng'}, {'name': 'name=huang'}, {'name': 'name=pan'}]
You use the same value of Dict for all of the iterations of the loop. So all of the dictionaries are the same. You just have three copies of the same dictionary in the list.
If you move the Dict = {} statement into the loop, it will be fixed.
a = ['name']
b = [('name=cheng',),('name=huang',),('name=pan',)]
c = []
for i in range(0,3):
Dict = {}
for j in range(0,1):
Dict[a[j]] = b[i][j]
c.append(Dict)
print(c)
Or more Pythonic:
keys = ['name']
values_list = [('name=cheng',), ('name=huang',), ('name=pan',)]
result = []
for values in values_list:
result.append(dict(zip(keys, values)))
print(result)
This works by using the zip builtin which does the same thing as [(x[i], y[i]) for i in range(min(len(x), len(y))] without needing to keep track of the indices or lengths.
The dict class can build a dictionary from a list of tuples, which is what this solution uses.

Nesting dictionaries with a for loop

I am trying to add a dictionary within a dictionary in the current code like this!
i = 0
A ={}
x = [...]
for i in x:
(a,b) = func(x)#this returns two different Dictionaries as a and b
for key in a.keys():
A[key] = {}
A[key][i] = a[key]
print('A:',A)
as I executed it, I am getting 'A' dictionary being printed throughout the loop! But, i need them in one single dictionary say: "C"
How do I do that?

Why am I getting the wrong values?

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.

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