Order of variables in python using the .update method of sets - python

How are the order of variables decided when updating a set?
A = {1, 2, 3, 4, 5}
A.add(8)
print(A)
A.update({-1, -2, -3})
print(A)
Why is the order {1, 2, 3, 4, 5, 8, -2, -3, -1} and not {1, 2, 3, 4, 5, 8, -1, -2, -3}?

When using {1, 2, 3} you generate a set, which is an unordered object.
You can't expect the set to conserve the order, because it uses a hashtable to avoid double entries of the same value. This is faster than using a list for this case.
When the order matters to you, than you have to use a list, on which you can call .append(element) or .insert(position, element).

order of elements in a set is undefined.unlike array so you couldn't reference to variable as A[0]=1
moreover, the set elements are usually not stored in order of appearance in the set; this allows checking if an element belongs to a set faster than just going through all the elements of the set.
you can check link below
https://snakify.org/en/lessons/sets/

Related

Why a method works differently with a list when stored in the variable and used and in other case not stored, but used directly?

This works..
indices = [1, 2, 3, 5, 8]
sample_reviews = reviews.loc[indices]
But... this does not works the same way, instead shows an error
sample_reviews = reviews.loc[1, 2, 3, 5, 8]
In the first case your are passing a list called indicies to the function, which is correct. In the second, you are passing 5 ints, which is incorrect. You need to change the second to:
sample_reviews = reviews.loc[[1, 2, 3, 5, 8]]

Why does list(set([2,1,3,6,5,3,6,4])) automatically order the list?

I was experimenting with set in python and while I understood that it is unsorted, based on hashes, I find it strange that it automatically sorts these numbers, both in Python 2 and in 3:
>>> list(set([2,1,3,6,5,3,6,4]))
[1, 2, 3, 4, 5, 6]
>>> list(set([2,1,3,6,5,3,6,4,0,7]))
[0, 1, 2, 3, 4, 5, 6, 7]
I googled for some time but didn't find the answer to the behavior of these two functions combined.
It does not, here is an example
In [2]: list(set([1,9,5,10]))
Out[2]: [1, 10, 5, 9]
Also, from the docs: https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset
A set object is an unordered collection of distinct hashable objects.
The reason sometimes you see the sorted output is dependent on how the hash is computed, and sometimes on what REPL is being used, and this behaviour is well described in this answer
Example for ipython, the way the set is printed, changes when we enable doctest_mode, which disables pretty-printing of ipython
In [1]: set([1,6,8,4])
Out[1]: {1, 4, 6, 8}
In [2]: %doctest_mode
Exception reporting mode: Plain
Doctest mode is: ON
>>> set([1,6,8,4])
{8, 1, 4, 6}
This is not a feature of sets and only a coincidence stemming from how sets are created.
The hash of the items in your list are the numbers themselves. So under some circumstances the created set will show this behaviour but is in no way reliable.
Looking at this answer you can read more about it.

Bisect keep indexes of inserted items

I am using the bisect module to keep a list sorted while inserting numbers.
Lets say I have am going to insert three numbers 9, 2, 5 in this order.
The last state of this list would be obviously [2, 5, 9], however, is there any chance that I can find the index list that numbers are inserted into this list. For this list it would be [1, 2, 0]. So the list I need is the indexes [0, 1, 2] after the sort is happened which in bisect is in happening with each insertion, thats why I could not find a way. I could just sort it with key feature of the sorted function however I dont want to increase the complexity. So my question is this achievable with the bisect module ?
Here is the code I use,
import bisect
lst = []
bisect.insort(lst, 9)
bisect.insort(lst, 2)
bisect.insort(lst, 5)
print lst
Edit: Another example would be, i am going to insert the numbers 4, 7, 1, 2, 9 to some empty list. (Let's first assume without bisect, that I already have the numbers in the list)
[4, 7, 1, 2, 9]
# indexes [0, 1, 2, 3, 4], typical enumeration
after sorting,
[1, 2, 4, 7, 9]
# now the index list [2, 3, 0, 1, 4]
Can it be done with bisect without increasing complexity.
Note: The order of the insertion is not arbitrary. It is known, thats why I try to use indexes with bisect.
insort has no idea in what order the items were inserted. You'll have to add that logic yourself. One way to do so could be to insert 2-tuples consisting of the value and the index:
bisect.insort(lst, (9, 0))
bisect.insort(lst, (2, 1))
bisect.insort(lst, (5, 2))
You would need to keep track of the index yourself as you're adding objects, but as sequences are sorted first by the first item, then by the next, etc., this will still sort properly without any extra effort.

Ordering a list of items based on their second value

The function needs to be able to take a list such as:
[("Alice", [1, 2, 1, 1, 1, 1]), ("Bob", [3, 1, 5, 3, 2, 5]), ("Clare", [2, 3, 2, 2, 4, 2]), ("Dennis", [5, 4, 4, 4, 3, 4]), ("Eva", [4, 5, 3, 5, 5, 3])]
and process the information to order it by the total of each of the results, and output the data in the original format but starting with the person with the lowest score and working downwards and it has to break ties using the first value in each. (The first result for each person)
What I have written so far can take one entry and work out the total score:
def result(name, a):
a.remove(max(a))
score = 0
for i in a:
score = score + i
return score
But I need to be able to adapt this to take any number of entries and be able to out more than just the total.
I know I need to have the function work out the total scores but be able to keep the original sets in tact but I don't know how to interact with just one part of an entry and iterate through all of them doing the same.
I'm using Python 3.4.
If I've understood your question properly, you'd like to sort the list, and have the sort order defined by the sum of the numbers provided in each tuple. So, Alice's numbers add up to 7, Clare's add up to 15, so Alice is before Clare.
sorted() can take a function to override the normal sort order. For example, you'd want:
sorted(data, key=lambda entry: sum(entry[1]))
This will mean that in order to work out what's bigger and smaller, sorted() will look at the sum of the list of numbers, and compare those. For example, when looking at Alice, the lambda (anonymous) function will be given ("Alice", [1, 2, 1, 1, 1, 1]), and so entry[1] is [1, 2, 1, 1, 1, 1], sum(entry[1]) is then 7, and that's the number that sorted() will use to put it in the right place.

Understanding the set() function

In python, set() is an unordered collection with no duplicate elements. However, I am not able to understand how it generates the output.
For example, consider the following:
>>> x = [1, 1, 2, 2, 2, 2, 2, 3, 3]
>>> set(x)
set([1, 2, 3])
>>> y = [1, 1, 6, 6, 6, 6, 6, 8, 8]
>>> set(y)
set([8, 1, 6])
>>> z = [1, 1, 6, 6, 6, 6, 6, 7, 7]
>>> set(z)
set([1, 6, 7])
Shouldn't the output of set(y) be: set([1, 6, 8])? I tried the above two in Python 2.6.
Sets are unordered, as you say. Even though one way to implement sets is using a tree, they can also be implemented using a hash table (meaning getting the keys in sorted order may not be that trivial).
If you'd like to sort them, you can simply perform:
sorted(set(y))
which will produce a sorted list containing the set's elements. (Not a set. Again, sets are unordered.)
Otherwise, the only thing guaranteed by set is that it makes the elements unique (nothing will be there more than once).
Hope this helps!
As an unordered collection type, set([8, 1, 6]) is equivalent to set([1, 6, 8]).
While it might be nicer to display the set contents in sorted order, that would make the repr() call more expensive.
Internally, the set type is implemented using a hash table: a hash function is used to separate items into a number of buckets to reduce the number of equality operations needed to check if an item is part of the set.
To produce the repr() output it just outputs the items from each bucket in turn, which is unlikely to be the sorted order.
As +Volatility and yourself pointed out, sets are unordered. If you need the elements to be in order, just call sorted on the set:
>>> y = [1, 1, 6, 6, 6, 6, 6, 8, 8]
>>> sorted(set(y))
[1, 6, 8]
Python's sets (and dictionaries) will iterate and print out in some order, but exactly what that order will be is arbitrary, and not guaranteed to remain the same after additions and removals.
Here's an example of a set changing order after a lot of values are added and then removed:
>>> s = set([1,6,8])
>>> print(s)
{8, 1, 6}
>>> s.update(range(10,100000))
>>> for v in range(10, 100000):
s.remove(v)
>>> print(s)
{1, 6, 8}
This is implementation dependent though, and so you should not rely upon it.
After reading the other answers, I still had trouble understanding why the set comes out un-ordered.
Mentioned this to my partner and he came up with this metaphor: take marbles. You put them in a tube a tad wider than marble width : you have a list. A set, however, is a bag. Even though you feed the marbles one-by-one into the bag; when you pour them from a bag back into the tube, they will not be in the same order (because they got all mixed up in a bag).

Categories