There is one question about Python3.6. It's about the output of Set expressions. I do not know why the code below does not appear in order:
a = {i*2 for i in range(1, 5)}
print(a)
I expect {2, 4, 6, 8} but the output is {8, 2, 4, 6}
Why it is not in order?
If you take a look at the documentation; the first sentence of the set documentation is:
A set object is an unordered collection of distinct hashable objects.
So the order of the elements in the set is for all practical purposes random. Even in python-3.6.
1here is the example in python, elements of the set doesn't arrange in order i.e elements are arrange in random
Python sets are not ordered, they only contain elements. If you need your data structure to have a certain order, maybe consider an OrderedDict.
Related
So I was converting a list with repetitive elements into a set to have each element appear once. I know that sets are unordered so they will display the elements in the order given. I ran the below script and I noticed a strange output.
mylist = [1,2,2,33,4,4,11,22,3,3,2]
print(set(mylist))
The output would be:
{1, 2, 33, 4, 3, 11, 22}
The 3 in the original list appears after the 11 and 22, so why does it appear before them in the set?
Sets in Python do not have an order
A set object is an unordered collection of distinct hashable objects.
Common uses include membership testing, removing duplicates from a
sequence, and computing mathematical operations such as intersection,
union, difference, and symmetric difference.
https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset
I am trying to find differences between MongoDB records. After performing my queries, I end up with a set of unique results (by applying set()).
Now, I want to compare a new extraction with the set that I just defined to see if there are any new additions to the record.
What I have done now is the following:
unique_documents = set([str(i) for i in dict_of_uniques[my_key]])
all_documents = [str(i) for i in (dict_of_all_docs[my_key])]
Basically I am trying to compare the string version of a dict among the two variables.
I have several approaches, among which unique_documents.difference(all_documents), but it keeps out returning an empty set. I know for a fact that the all_documents variable contains two new entries in the record. I would like to know which ones are they.
Thank you,
If all_documents is the set with new elements that you want to get as the result, then you need to reverse the order of the arguments to the difference method.
unique_documents = set([str(i) for i in dict_of_uniques[my_key]])
all_documents = set([str(i) for i in (dict_of_all_docs[my_key])])
all_documents.difference(unique_documents)
See how the order matters:
>>> x = set([1,2,3])
>>> y = set([3,4,5])
>>> x.difference(y)
{1, 2}
>>> y.difference(x)
{4, 5}
difference gives you the elements of the first set that are not present in the second set.
If you want to see things that were either added or removed, you can symmetric_difference. This function is described as "symmetric" because it gives the same results regardless of argument order.
>>> x.symmetric_difference(y)
{1, 2, 4, 5}
>>> y.symmetric_difference(x)
{1, 2, 4, 5}
It is hard to tell without a description of the dictionary structure but your code seems to be comparing single keys only. If you want to compare the content of both dictionaries, you need to get all the values:
currentData = set( str(rec) for rec in dict_of_all_docs.values() )
changedKeys = [k for k,value in dict_of_fetched.items() if str(value) not in currentData]
This doesn't seem very efficient though but without more information on the data structure, it is hard to make a better suggestion. If your records can already matched by a dictionary key, you probably don't need to use a set at all. A simple loop should do.
Rather than unique_documents.difference(all_documents) use all_documents.difference(unique_documents)
More on Python Sets
Python sorts lists of tuples by looking at the elements of the tuples, in order. Since sets are unordered, how does Python sort a list of sets?
Edit: The question and accepted answer in this post are more general and the document given is very in-depth. My question is not a duplicate.
Regardless of what's in a list, the elements' __lt__ methods are the only comparison methods consulted. For sets, a < b means "a is a proper subset of b", which isn't enough to define a total order. That's why the result is, in general, undefined. It may be any permutation of the original list consistent with which pairs of list elements the implementation happens to apply __lt__ to.
If, for every pair of sets in the list, one is in fact a proper subset of the other, then the list will be sorted from smallest (cardinality) set to largest. Otherwise little can be said. For example:
>>> sorted([{5, 6}, {3, 4}, {5}, {3}]) # nothing changes
[{5, 6}, {3, 4}, {5}, {3}]
What happens is a consequence of undefined implementation details. Since I wrote list.sort(), I know what happens in this case, but it's not guaranteed to always work this way:
First the implementation asks "is {3, 4} < {5, 6}?". No, so the order of the first two elements is consistent with being sorted already. It next asks "is {5} < {3, 4}?". No, so the first three elements appear to be already sorted. Finally it asks "is {3} < {5}?". No again, so the original list's entire order is consistent with being already sorted, and nothing changes.
A future implementation may, e.g., ask "is {5} < {5, 6}?" at some point, and since "yes" decide {5} needs to appear before {5, 6}. So the result is simply not defined.
Sets are partially ordered, so
the output of the list.sort() method is undefined for lists of sets.
https://docs.python.org/3/library/stdtypes.html#set
The __le__ operator on sets define the partial ordering "subset". Therefore the sorted order is undefined.
{3} < {5} is false, but so is {5} < {3} so the sort algorithm will usually not rearrange them.
Citation from Python3 documentaton about sets:
The subset and equality comparisons do not generalize to a total ordering function. For example, any two nonempty disjoint sets are not equal and are not subsets of each other, so all of the following return False: a<b, a==b, or a>b.
Since sets only define partial ordering (subset relationships), the output of the list.sort() method is undefined for lists of sets.
I have 15 dicts like the following 3 (all 15 are of varying lengths).
For example:
HQDict = {'HQ1':10, 'HQ2':3, 'HQ3':5}
BADict = {'BA1':15, 'BA2':4, 'BA3':3}
STDict = {'ST1':5, 'ST2':4, 'ST3':3}
I want to create all the possible combinations of the 15 dicts with only one element selected from each dict with the values added together and the keys stored in a list. I have been able to get all the information into the respective dicts but I am clueless on where to start with the combinations, I have seen itertools.combinations but I'm not sure how to make it only select 1 element from each dict. If you need any more information please ask and I will be happy to edit.
Edit1:
I also needed to add that the values are additive so value of BA2 will be the value of BA1 + BA2 and that the combination could be a list of 1.
list=[HQ1,BA2,ST1]
value=34
next permutation
list=[HQ2]
value=13
Edit2:
Rather than try and create the combinations of the dicts the end goal is to give the function a total and it will return all the possible combinations of buildings (each dict represents a building and each item in the dict a level) that add up to that total. So for example:
combinations(34) would return
[HQ1,BA2,ST1]
and combinations(13 would return
[HQ2]
pastebin to file containing all buildings and code im using to create the dicts : link to pastebin
I have seen itertools.combinations but I'm not sure how to make it only select 1 element from each dict.
Use itertools.product(..) instead. It takes a varying list of arguments each corresponding to a list of options to pick in one iteration:
>>> map(dict, product(HQDict.items(), STDict.items(), BADict.items()))
[{'HQ1': 10, 'BA2': 4, 'ST1': 5}, {'HQ1': 10, 'ST1': 5, 'BA3': 3}, ...... ]
If you have 15 such dicts, I'd suggest putting all of them in a list, and calling product like below:
>>> map(dict, product(*list_of_dicts))
EDIT: In python3, you will get a map object back, and you'll have to iterate over it to get the actual values. You can convert it to a list, but will defeat the purpose of map returning something that you can iterate over. You can convert to a list like:
>>> [dict(x) for x in product(HQDict.items(), STDict.items(), BADict.items())]
[{'HQ1': 10, 'BA2': 4, 'ST1': 5}, {'HQ1': 10, 'ST1': 5, 'BA1': 15}, ..]
I am in simple doubt... I created the following dictionary:
>>> alpha={'a': 10, 'b': 5, 'c': 11}
But, when I want to see the dictionary keys and values I got:
>>> alpha
{'a': 10, 'c': 11, 'b': 5}
See that the "b" and "c" has swapped their position. How can I make the position be the same of the moment that the dictionary was created?
Dictionaries are unordered containers - if you want to preserve order, you can use collections.OrderedDict (Python 2.7 or later), or use another container type which is naturally order-preserving.
Generally if you have an access pattern that cares about ordered retrieval then a dictionary is solving a problem you don't have (fast access to random elements), while giving you a new one.
Dictonaries are not guaranting sorting of keys. You can find this information in python docs: http://docs.python.org/tutorial/datastructures.html#dictionaries
You can always sort dictionary keys or use other, more specialized collection.