I want to make a custom sort for my Python code that uses the built in sort() function, but can sort a list based on two values. The list I want sorted is structured as a list of tuples, which each contain 2 integers. What I want to sort to do is sort the list of tuples based on each of their first integers, but if two first integers are tied, it refers to their second integer, which is unique and therefore will not be the same. I want to use the speed of the built in sort() function, but be able to sort in this way. Any and all help is GREATLY APPRECIATED!
Built in sorted does this.
>>> l = [(1, 1), (1, 2), (2, 5), (2, 4)]
>>> sorted(l)
[(1, 1), (1, 2), (2, 4), (2, 5)]
The difference between sort() and sorted() is that sort() modifies the given list (and therefore, any other lists that are sharing its structure), while sorted() accepts an iterable, and returns a brand new list object.
For instance:
>>> a = list("alphabet")
>>> a
['a', 'l', 'p', 'h', 'a', 'b', 'e', 't']
>>> b = a
>>> b
['a', 'l', 'p', 'h', 'a', 'b', 'e', 't']
>>> b.sort()
>>> #this has modified the shared structure
>>> a
['a', 'a', 'b', 'e', 'h', 'l', 'p', 't']
As opposed to sorted()
>>> c = list("alphabet")
>>> d = c
>>> sorted(d)
['a', 'a', 'b', 'e', 'h', 'l', 'p', 't']
>>> c
['a', 'l', 'p', 'h', 'a', 'b', 'e', 't']
sorted() is safer.
You have just described the exact behavior of the list.sort() method, so once you have the tuples in a list, simply call the list's sort method (l.sort) with no arguments and it will be put in the desired order.
When more complex sorts are required you can pass a "key function" as a named argument, key. The function is applied to each element of the list to generate a sort key, then the elements are sorted in the order of their sort keys.
The sorted built-in function is convenient when you require a sorted copy of a list - it simply saves you the trouble of creating a copy then calling its sort method.
Related
When I run the following code I get rows of tuples:
{perm = itertools.permutations(['A','B','C','D','E','F'],4)
for val in perm:
print(val)}.
How do I make the code give me the output as a single list of lists instead of rows of tuples?
When I run the code I get something like this
('F', 'E', 'B', 'C')
('F', 'E', 'B', 'D')
('F', 'E', 'C', 'A')
('F', 'E', 'C', 'B')
type here
etc.
What I want is something like this
[['F', 'E', 'B', 'C'],
['F', 'E', 'B', 'D'],
['F', 'E', 'C', 'A'],...,]
cast val into a list and append it to another list.
import itertools
perm = itertools.permutations(['A','B','C','D','E','F'],4)
result = []
for val in perm:
result.append(list(val))
print(result)
The question is, do you want to generate all permutations and store them?
As you have it now, the generator will give you one permutation each time, which is memory efficient.
You can generate all of them into a list of lists, but just think if you really want that, since the number of permutations could be very large.
How do I add a list of values to an existing set?
Adding the contents of a list
Use set.update() or the |= operator:
>>> a = set('abc')
>>> a
{'a', 'b', 'c'}
>>> xs = ['d', 'e']
>>> a.update(xs)
>>> a
{'e', 'b', 'c', 'd', 'a'}
>>> xs = ['f', 'g']
>>> a |= set(xs)
>>> a
{'e', 'b', 'f', 'c', 'd', 'g', 'a'}
Adding the list itself
It is not possible to directly add the list itself to the set, since set elements must be hashable.
Instead, one may convert the list to a tuple first:
>>> a = {('a', 'b', 'c')}
>>> xs = ['d', 'e']
>>> a.add(tuple(xs))
>>> a
{('a', 'b', 'c'), ('d', 'e')}
You can't add a list to a set because lists are mutable, meaning that you can change the contents of the list after adding it to the set.
You can however add tuples to the set, because you cannot change the contents of a tuple:
>>> a.add(('f', 'g'))
>>> print a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
Edit: some explanation: The documentation defines a set as an unordered collection of distinct hashable objects. The objects have to be hashable so that finding, adding and removing elements can be done faster than looking at each individual element every time you perform these operations. The specific algorithms used are explained in the Wikipedia article. Pythons hashing algorithms are explained on effbot.org and pythons __hash__ function in the python reference.
Some facts:
Set elements as well as dictionary keys have to be hashable
Some unhashable datatypes:
list: use tuple instead
set: use frozenset instead
dict: has no official counterpart, but there are some
recipes
Object instances are hashable by default with each instance having a unique hash. You can override this behavior as explained in the python reference.
To add the elements of a list to a set, use update
From https://docs.python.org/2/library/sets.html
s.update(t): return set s with elements added from t
E.g.
>>> s = set([1, 2])
>>> l = [3, 4]
>>> s.update(l)
>>> s
{1, 2, 3, 4}
If you instead want to add the entire list as a single element to the set, you can't because lists aren't hashable. You could instead add a tuple, e.g. s.add(tuple(l)). See also TypeError: unhashable type: 'list' when using built-in set function for more information on that.
Hopefully this helps:
>>> seta = set('1234')
>>> listb = ['a','b','c']
>>> seta.union(listb)
set(['a', 'c', 'b', '1', '3', '2', '4'])
>>> seta
set(['1', '3', '2', '4'])
>>> seta = seta.union(listb)
>>> seta
set(['a', 'c', 'b', '1', '3', '2', '4'])
Please notice the function set.update(). The documentation says:
Update a set with the union of itself and others.
list objects are unhashable. you might want to turn them in to tuples though.
Sets can't have mutable (changeable) elements/members. A list, being mutable, cannot be a member of a set.
As sets are mutable, you cannot have a set of sets!
You can have a set of frozensets though.
(The same kind of "mutability requirement" applies to the keys of a dict.)
Other answers have already given you code, I hope this gives a bit of insight.
I'm hoping Alex Martelli will answer with even more details.
I found I needed to do something similar today. The algorithm knew when it was creating a new list that needed to added to the set, but not when it would have finished operating on the list.
Anyway, the behaviour I wanted was for set to use id rather than hash. As such I found mydict[id(mylist)] = mylist instead of myset.add(mylist) to offer the behaviour I wanted.
You want to add a tuple, not a list:
>>> a=set('abcde')
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> l=['f','g']
>>> l
['f', 'g']
>>> t = tuple(l)
>>> t
('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
If you have a list, you can convert to the tuple, as shown above. A tuple is immutable, so it can be added to the set.
You'll want to use tuples, which are hashable (you can't hash a mutable object like a list).
>>> a = set("abcde")
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> t = ('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
Here is how I usually do it:
def add_list_to_set(my_list, my_set):
[my_set.add(each) for each in my_list]
return my_set
Try using * unpack, like below:
>>> a=set('abcde')
>>> a
{'a', 'd', 'e', 'b', 'c'}
>>> l=['f','g']
>>> l
['f', 'g']
>>> {*l, *a}
{'a', 'd', 'e', 'f', 'b', 'g', 'c'}
>>>
Non Editor version:
a=set('abcde')
l=['f', 'g']
print({*l, *a})
Output:
{'a', 'd', 'e', 'f', 'b', 'g', 'c'}
Union is the easiest way:
list0 = ['a', 'b', 'c']
set0 = set()
set0.add('d')
set0.add('e')
set0.add('f')
set0 = set0.union(list0)
print(set0)
Output:
{'b', 'd', 'f', 'c', 'a', 'e'}
Im using a function to parse an excel in python without using libraries but importing an individual script accessing the excel data. my program can read the excel data and with following structure gets the values. I need to access specific columns of the listExcelvalues as follow and pay it to the input of other function :
actual code
ive converted the list into the dict but the problem is I dont want to pass all the dictionary as input of other function but instead specific columns.
Any ideas how to do so ?
As I understand you have a structure like this:
>>> l=[['a','b','c','d'],['e','f','g','h'],['i','j','k','l'],['m','n','o','p']]
>>> m=list(enumerate(l,0))
>>> m
[(0, ['a', 'b', 'c', 'd']), (1, ['e', 'f', 'g', 'h']), (2, ['i', 'j', 'k', 'l']), (3, ['m', 'n', 'o', 'p'])]
Then you can access rows like this. Here is the second row (counting from zero):
>>> row=m[2][1]
>>> row
['i', 'j', 'k', 'l']
>>> hrow=m[2]
>>> hrow
(2, ['i', 'j', 'k', 'l'])
And columns too. Here is the second (counting from zero) column:
>>> col=[]
>>> for r in m:
... col.append(r[1][2])
>>> col
['c', 'g', 'k', 'o']
You want to take a subset of your dict. You may want to try this out:
new_dict = {k:v if k in list_of_req_cols for k,v in original_dict.items()}
So I have a list that holds a set of alphabetical values, that are names in a dictionary, for example:
['H', 'I', 'B']
Where the individual variable names are keys that i am using in a dictionary, but my problem is, the list of HIB together represents another variable, that i wish to define in the dictionary as a keyword of HIB. So my question is, how do i convert this list into a variable, preferably:
nodeName = 'HIB'
So I can then assign it a key in my dictionary using:
Tree[nodeName] = ...
Because obv. you cannot call lists in dictionaries.
thanks!
>>> ''.join(['H', 'I', 'B'])
'HIB'
or you can convert it to a tuple:
>>> tuple(['H', 'I', 'B'])
or generally
>>> tuple(li)
which can be used as a dictionary key.
my_list = ['H', 'I', 'B']
"".join(my_list)
>> 'HIB'
The better approach, as suggested by others is to use a tuple:
my_list = ['H', 'I', 'B']
tuple(my_list)
>> ('H', 'I', 'B')
This will resolve the ambiguity when trying to decide whether 'HIB' was created from ['H', 'I', 'B'] or from ['HI', 'B']
How do I add a list of values to an existing set?
Adding the contents of a list
Use set.update() or the |= operator:
>>> a = set('abc')
>>> a
{'a', 'b', 'c'}
>>> xs = ['d', 'e']
>>> a.update(xs)
>>> a
{'e', 'b', 'c', 'd', 'a'}
>>> xs = ['f', 'g']
>>> a |= set(xs)
>>> a
{'e', 'b', 'f', 'c', 'd', 'g', 'a'}
Adding the list itself
It is not possible to directly add the list itself to the set, since set elements must be hashable.
Instead, one may convert the list to a tuple first:
>>> a = {('a', 'b', 'c')}
>>> xs = ['d', 'e']
>>> a.add(tuple(xs))
>>> a
{('a', 'b', 'c'), ('d', 'e')}
You can't add a list to a set because lists are mutable, meaning that you can change the contents of the list after adding it to the set.
You can however add tuples to the set, because you cannot change the contents of a tuple:
>>> a.add(('f', 'g'))
>>> print a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
Edit: some explanation: The documentation defines a set as an unordered collection of distinct hashable objects. The objects have to be hashable so that finding, adding and removing elements can be done faster than looking at each individual element every time you perform these operations. The specific algorithms used are explained in the Wikipedia article. Pythons hashing algorithms are explained on effbot.org and pythons __hash__ function in the python reference.
Some facts:
Set elements as well as dictionary keys have to be hashable
Some unhashable datatypes:
list: use tuple instead
set: use frozenset instead
dict: has no official counterpart, but there are some
recipes
Object instances are hashable by default with each instance having a unique hash. You can override this behavior as explained in the python reference.
To add the elements of a list to a set, use update
From https://docs.python.org/2/library/sets.html
s.update(t): return set s with elements added from t
E.g.
>>> s = set([1, 2])
>>> l = [3, 4]
>>> s.update(l)
>>> s
{1, 2, 3, 4}
If you instead want to add the entire list as a single element to the set, you can't because lists aren't hashable. You could instead add a tuple, e.g. s.add(tuple(l)). See also TypeError: unhashable type: 'list' when using built-in set function for more information on that.
Hopefully this helps:
>>> seta = set('1234')
>>> listb = ['a','b','c']
>>> seta.union(listb)
set(['a', 'c', 'b', '1', '3', '2', '4'])
>>> seta
set(['1', '3', '2', '4'])
>>> seta = seta.union(listb)
>>> seta
set(['a', 'c', 'b', '1', '3', '2', '4'])
Please notice the function set.update(). The documentation says:
Update a set with the union of itself and others.
list objects are unhashable. you might want to turn them in to tuples though.
Sets can't have mutable (changeable) elements/members. A list, being mutable, cannot be a member of a set.
As sets are mutable, you cannot have a set of sets!
You can have a set of frozensets though.
(The same kind of "mutability requirement" applies to the keys of a dict.)
Other answers have already given you code, I hope this gives a bit of insight.
I'm hoping Alex Martelli will answer with even more details.
I found I needed to do something similar today. The algorithm knew when it was creating a new list that needed to added to the set, but not when it would have finished operating on the list.
Anyway, the behaviour I wanted was for set to use id rather than hash. As such I found mydict[id(mylist)] = mylist instead of myset.add(mylist) to offer the behaviour I wanted.
You want to add a tuple, not a list:
>>> a=set('abcde')
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> l=['f','g']
>>> l
['f', 'g']
>>> t = tuple(l)
>>> t
('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
If you have a list, you can convert to the tuple, as shown above. A tuple is immutable, so it can be added to the set.
You'll want to use tuples, which are hashable (you can't hash a mutable object like a list).
>>> a = set("abcde")
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> t = ('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
Here is how I usually do it:
def add_list_to_set(my_list, my_set):
[my_set.add(each) for each in my_list]
return my_set
Try using * unpack, like below:
>>> a=set('abcde')
>>> a
{'a', 'd', 'e', 'b', 'c'}
>>> l=['f','g']
>>> l
['f', 'g']
>>> {*l, *a}
{'a', 'd', 'e', 'f', 'b', 'g', 'c'}
>>>
Non Editor version:
a=set('abcde')
l=['f', 'g']
print({*l, *a})
Output:
{'a', 'd', 'e', 'f', 'b', 'g', 'c'}
Union is the easiest way:
list0 = ['a', 'b', 'c']
set0 = set()
set0.add('d')
set0.add('e')
set0.add('f')
set0 = set0.union(list0)
print(set0)
Output:
{'b', 'd', 'f', 'c', 'a', 'e'}