Python dictionary, lists ,join and Interpreter [duplicate] - python

This question already has answers here:
Why is the order in dictionaries and sets arbitrary?
(5 answers)
Closed 5 years ago.
join in python joins the list elements and keys in dictionaries right?.
Whenever I use join to join a list the output is in the same order as the list. I know it not ordered and the output clearly differed when i gave the same in a file and in the interpreter.
My question is how interpreter remembers that and gives the same output everytime for that order. Is it in some sort of cache or??
>>> x = ['a','b','c']
>>> ','.join(x)
'a,b,c'
>>> x = ['c','b','a']
>>> ','.join(x)
'c,b,a'
using a dict
>>> z = {'a':3,'b':1,'c':4,'d':2}
>>> ','.join(z)
'b,d,a,c'
>>> z = {'a':3,'d':1,'c':4,'b':2}
>>> ','.join(z)
'c,d,a,b'
So I concluded that it varies each time but when I give the same dictionary with a specific order after several instructions it still displays the output in some order which is the same everytime in the interpreter!
>>> z = {'foo':3,'bar':1,'egg':4,'spam':2}
>>> ','.join(z)
'egg,bar,foo,spam'
>>> z = {'bar':3,'foo':1,'egg':4,'spam':2}
>>> ','.join(z)
'egg,bar,foo,spam'
>>> z = {'bar':3,'foo':1,'spam':4,'egg':2}
>>> ','.join(z)
'spam,bar,foo,egg'
>>> z = {'foo':3,'bar':1,'egg':4,'spam':2}
>>> ','.join(z)
'egg,bar,foo,spam'
I maybe missing something out but how does the interpreter remember it. Clear explanations would help greatly.
NOTE: As seen in the comments mentioned by chris_rands
I quote 'the dict iteration is fixed within an interpreter session because the environmental variable PYTHONHASHSEED is fixed'
is more along the lines of the answer I am looking for. Explanations would be great!.

dictionaries dont have an order in python. You might randomly get the same order, but it's not guaranteed. If you need a dictionary with a fixed order, have a look at OrderedDict: https://docs.python.org/2/library/collections.html#collections.OrderedDict

You can use sortedcontainers, and then join
from sortedcontainers import SortedDict
z={'egg': 4, 'foo': 3, 'bar': 1, 'spam': 2}
','.join(SortedDict(z))
#'bar,egg,foo,spam'
in natural case :
','.join(dict(SortedDict(z))) #or ','.join(z)
#'egg,foo,bar,spam'

Related

How to unpack dict with one key-value pair to two variables more elegantly? [duplicate]

This question already has answers here:
How to extract dictionary single key-value pair in variables
(11 answers)
Closed 3 years ago.
Currently, I'm using this:
d = {'a': 'xyz'}
k, v = list(*d.items())
The starred expression is required here, as omitting it causes the list function/constructor to return a list with a single tuple, which contains the key and value.
However, I was wondering if there were a better way to do it.
Keep nesting:
>>> d = {'a': 'xyz'}
>>> ((k,v),) = d.items()
>>> k
'a'
>>> v
'xyz'
Or equivalently:
>>> (k,v), = d.items()
>>> k
'a'
>>> v
'xyz'
>>>
Not sure which I prefer, the last one might be a bit difficult to read if I was glancing at it.
Note, the advantage here is that it is non-destructive and fails if the dict has more than one key-value pair.
Since dict items do not support indexed access, you might resort to the following non-mutating retrieval of the first (and only) item:
k, v = next(iter(d.items()))
This has the advantage of not only working for dicts of any size, but remaining an O(1) operation which other solutions that unpack the items or convert them to a list would not.
If you don't mind the dictionary getting altered, this'll do:
k, v = d.popitem()

Able to retrieve zipped values only once in python? [duplicate]

This question already has answers here:
The zip() function in Python 3
(2 answers)
Closed last month.
Created two lists in python and zipped them using zip function and saved them to a variable. Tried to print it to the console and was able to print successfully and when i tried again,empty list is printed.screenshot
Same with tuples.screenshot
Why i am able to retrieve values only once? Am in doing something wrong?
Python 3.7.1
The zip function is actually just an iterator -- an iterator can only be traversed once. If you want to be able to iterate over it multiple times, convert it to a list first.
a = [1,2,3]
b = [1,2,3]
c = list(zip(a, b))
Why is this?
Because those are similar to generators, so you can print first time, but when you try to print it again, it starts from the end, and no values left, see an example (clearer than yours):
>>> l=[1,2,3,4]
>>> it=iter(l) # generator basically (as in your question, zip, is also considered as a geneartor here)
>>> list(it)
[1, 2, 3, 4]
>>> list(it)
[]
>>>
So how to solve this issue?
Simply just replace this line:
zipped_list = zip(list1,list2)
With:
zipped_list = list(zip(list1,list2))
Then everything would work fine.

python dict not displayed in order [duplicate]

This question already has answers here:
How do I sort a dictionary by key?
(32 answers)
Closed 5 years ago.
Could you please tell me whats the difference between python dict on below two cases. First one prints the data in correct order but on second iteration P6 take precedence over P5. What will be the reason?
>>> a=["P3", "P4"]
>>> devices_by_dc = {}
>>> for b in a:
... devices_by_dc[b] = {}
>>> print devices_by_dc
{'P3': {}, 'P4': {}}
>>> a=["P5", "P6"]
>>> devices_by_dc = {}
>>> for b in a:
... devices_by_dc[b] = {}
{'P6': {}, 'P5': {}}
In Python, dictionaries are not ordered, they are a set-like objects. Therefore the order of printing it is completely random.
Consider dict.keys(). That is a set. So basically when you do
print(dict)
what actually happens is
for key in dict.keys():
str_out = ' \'{0}\': {1},'.format(key, dict[key]
print '{{ {0} }}'.format(str_out[:-1])
And since dict.keys() is a set, the order of selecting keys is random.
If you want to introduce order into dictionary, then instead of dict use collections.OrderedDict as suggested in the comment to the question. Don't forget to import collections.
Dictionaries in python are not ordered by default. You can use an OrderedDict instead.
import collections
devices_by_dc = collections.OrderedDict()
for b in a:
devices_by_dc[b] = {}

how to ignore the order of elements in a tuple

I am using tuples as the key for a dictionary I created. For example:
example_dict = {}
example_dict[("A", "B")] = "1"
Later when I wish to modify the value of an entry in the dictionary I don't currently have control over the order of the tuple. For example:
("B", "A") may be the case, instead of ("A", "B")
I'm aware that these tuples are not equal from a simple == comparison that I tried in the python shell.
What I am wondering is how I could work around this? How could I make the following not produce a KeyError:
print (example_dict["B", "A"])
Is there a way to consistently order the elements of a tuple? Is there a way to ignore order completely? Any other work arounds? I'm aware I could just include all arrangements of the tuples as keys in the dictionary, and then collate the values of the different permutations later. I strongly want to avoid doing this as that only adds difficulty and complexity to the problem.
The usual ways are to either sort the keys:
example_dict[tuple(sorted(key_tuple))] = "1"
use frozensets as keys (if there won't be duplicate elements in the tuples):
example_dict[frozenset(key_tuple)] = "1"
or use frozensets of (item, count) tuples as keys (if there can be duplicate elements in the tuples):
example_dict[frozenset(Counter(key_tuple).viewitems())] = "1"
Whichever option you choose, you'll have to apply the same transformation when you look up values.
You want your dictionary keys to be "sets" (a set is a collection for which an item is either in or not in the set, but that has no concept of order). Luckily python has what you need. Specifically because you need something hashable you want to use frozenset.
>>> example_dict = {}
>>> example_dict[frozenset(("A", "B"))] = "1"
>>> example_dict[frozenset(("B", "A"))]
'1'
>>> example_dict[frozenset(("A", "B"))]
'1'
Instead of using a tuple, use a frozenset. A frozenset is just a constant set, just as a tuple can be thought of as a constant list.
Here's an example (from Python 3, but it will work in Python 2 as well):
>>> d = {}
>>> k1 = frozenset((1, 2))
>>> k2 = frozenset((2, 1))
>>> k1
frozenset({1, 2})
>>> k2
frozenset({1, 2})
>>> k1 == k2
True
>>> d[k1] = 123
>>> d[k2]
123
>>>

Initializing Python dictionary using dict() vs {} [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 7 years ago.
I am witnessing a very weird behviour with the following Python code snippet.
list_of_dict = [{}]*2 # create a list of 2 dict
list_of_dict[0]["add_to_dict_0"] = 1 # add a (key,val) pair to 1st dict
print list_of_dict[0]
print list_of_dict[1]
The output is:
{'add_to_dict_0': 1}
{'add_to_dict_0': 1}
Both the dictionaries got updated, although I (explicitly) updated only one. However, changing the initialization in Line 1 to the following:
list_of_dict = [dict() for _ in xrange(0,2)]
fixes the issue.
What is the reason for this behaviour? I am guessing that this is an artefact of the concept of name-object binding in Python (as opposed to variable-memory location binding in other languages like C/C++). My guess is that in the first case, both list_of_dict[0] and list_of_dict[1] are bound to the same dictionary object.
Is my suspicion correct? If yes, then why is the behaviour not replicated in the second case? What is the difference between dict_object = dict() and dict_object = {}?
There is no difference between dict_object = dict() and dict_object = {}
The problem here is [{}] * 2 will generate a list with 2 elements which are reference to a single object. [{} for x in range(2)] will generate a list with two elements which are reference two distinct objects.
Replacing {} with dict() will get the same result.
Both the dictionary in the list pointing to same object, Hence modifying one will will change others also
>>> list_of_dict = [{}]*2
>>> id(list_of_dict[0])
50030176
>>> id(list_of_dict[1])
50030176
When you created two empty dictionary by using dict(), dict() return different object every time
>>> d1 = dict()
>>> d2 = dict()
>>> id(d1)
50074656
>>> id(d2)
50074512

Categories

Resources