Why this Python expression doesn't produce expected result? - python

This code snippet:
a = [3, 2, 1]
a.sort()
produces [1, 2, 3] list. Why
[3, 2, 1].sort()
doesn't produce the same result? Is there a "one-liner" to accomplish this?

You can use
sorted_array = sorted([2,3,1])

>>> [3, 2, 1].sort()
It does sort this list object but as the number of references(variables pointing) to this list are 0, so it is garbage collected.(i.e we can't access this list anymore)
Coming to your first question, list.sort() sorts a list in-place and returns None.
>>> a = [3, 2, 1]
>>> a.sort()
>>> a
[1, 2, 3]
If you want a to stay as it is, use sorted and assign the result back to some variable.
>>> a = [3, 2, 1]
>>> b = sorted(a)
>>> b
[1, 2, 3]
>>> a
[3, 2, 1]

list.sort is a method that sorts an existing list therefore returning None
sorted is a builtin function that creates a new sorted list from its input and returns it.

Related

Difference between sort and sorted and their reverse in python?

I was trying to grasp my head around the difference between .sort() and sorted() and their reverse in python but I don't seem to get any. Any help?
The difference is that sorted(l) returns a copy of l without changing it, while l.sort() changes l. See the example below:
l = [3, 2, 4, 5, 1, 7]
l.sort()
==> returns None, but changes l
print(l) # As you can see, l is now sorted.
==> [1, 2, 3, 4, 5, 7]
# Create an unsorted list, again
l = [3, 2, 4, 5, 1, 7]
print(sorted(l))
==> [1, 2, 3, 4, 5, 7] # sorted(l) returns a sorted list
print(l) # but l itself didn't change.
==> [3, 2, 4, 5, 1, 7]
.sort() is a list method whereas sorted() is a built-in function but they effectively do the same thing.
For example...
my_list = [2,6,5,1,3]
my_list.sort()
print(my_list)
>>>[1, 2, 3, 5, 6]
The sort() method changes the my_list variable. You can add a reverse = True parameter into the parenthesis to reverse the list...
my_list = [2,6,5,1,3]
my_list.sort(reverse = True)
print(my_list)
>>>[6, 5, 3, 2, 1]
The sorted() function is different as it cannot chnage the my_list variable. eg...
my_list = [2,6,5,1,3]
sorted(my_list)
print(my_list)
>>>[2, 6, 5, 1, 3]
Instead you can assign the sorted(my_list) to a new variable...
my_list = [2,6,5,1,3]
new_list = sorted(my_list)
print(new_list)
>>>[1, 2, 3, 5, 6]
And if you want to reverse this list you can add reverse = True into the parenthesis...
my_list = [2,6,5,1,3]
variable = sorted(my_list, reverse = True)
print(variable)
>>>[6, 5, 3, 2, 1]
I think .sort() is a list method which sorts the list and sorted is a builtin function which accpets some iterable object and returns its sorted copy
The difference between sort and sorted is that sorted(list) returns a copy of the list without changing it, while list.sort() changes the list.
Therefore, sorted is a static method, while sort is a list instance method.

Adjustable lambda to different lists

I am sorting different lists. For example:
One list has 3 integers: [[3, 4, 2], [3, 5, 3]]
The other has 4: [[3, 4, 2, 4], [3, 5,3 ,2]]
Like this there are more, ranging from two to five integers.
I could do this manually for every list, but since I'm still learning I could ask how this is done automatically!
So I have this code for rearranging the list in descending order
l.sort(key=lambda x: [x[0], x[1], x[2], x[3]], reverse = True)
This would work for the second example, but for the first example it would give:
IndexError: list index out of range
So my thought was something like this:
key = lambda x: [x[i] for i in range(len(l[0]))]
but it didn't work..
Does anybody knows if in this situation you can have an adjustable lambda?
I'm not quite sure if I get your question correctly, as you talk about one list in each case but then again show lists looking like lists of lists.
So for the simple case of a normal list, python provides sorting already, you don't need lambda:
>>> a = [3,2,7,1,11]
>>> b = sorted(a)
>>> b
[1, 2, 3, 7, 11]
>>> b = sorted(a, reverse=True)
>>> b
[11, 7, 3, 2, 1]
>>>
Check here for more options on sorting: https://docs.python.org/3/howto/sorting.html
Now if you have a list of lists, you could go for something like this:
>>> a = [[1,5,2],[3,4,1]]
>>> a
[[1, 5, 2], [3, 4, 1]]
>>> for idx,ls in enumerate(a):
a[idx] = sorted(ls, reverse=True)
>>> a
[[5, 2, 1], [4, 3, 1]]
which you could then use in a map function if you wanted to use a lambda:
>>> a = [[1,5,2],[3,4,1]]
>>> b = map(lambda x: sorted(x, reverse=True),a)
>>> b
<map object at 0x03C0F220>
>>> list(b)
[[5, 2, 1], [4, 3, 1]]
>>>
Note to put the list keyword infront of the map object to make it a list.

How to insert a list at a specific index?

I got a list
a=[1,2,3]
and a list of list
b=[[1,2],[3,4,5]]
and I want to insert a into b at index 1 so b becomes
b=[[1,2],[1,2,3],[3,4,5]]
How do I do that?If I use insert it won't work because I can only insert an item not a list?
EDIT:I realised insert can be used for lists as well.Thanks.
You can use list.insert which takes the index as the first argument
>>> a=[1,2,3]
>>> b=[[1,2],[3,4,5]]
>>> b.insert(1, a)
>>> b
[[1, 2], [1, 2, 3], [3, 4, 5]]
You can use list slicing:
b=[[1,2],[3,4,5]]
a = [1, 2, 3]
final_list = b[:1]+[a]+b[1:]
Output:
[[1, 2], [1, 2, 3], [3, 4, 5]]

Optimal method to find the max of sublist items within list

I have a multidimensional list in the format:
list = [[1, 2, 3], [2, 4, 2], [0, 1, 1]]
How do I obtain the maximum value of the third value of all the sublists. In pseudo code:
max(list[0][2], list[1][2], list[2][2])
I know this can be done via iterating over the list and extracting the third value into a new list, then simply performing max(list), but I'm wondering if this can be done using a lambda or list comprehension?
Just use max with a generator expression:
>>> lst = [[1, 2, 3], [2, 4, 2], [0, 1, 1]]
>>> max(l[2] for l in lst)
3
Also, don't name your variables list, you are shadowing the type.
Use zip function to get the list of columns then use a simple indexing in order to get the expected column:
>>> lst = [[1, 2, 3], [2, 4, 2], [0, 1, 1]]
>>>
>>> max(zip(*lst)[-1]) # in python 3.x max(list(zip(*lst))[-1])
3
One another alternative and more pythonic approach is passing a key function to max to get the max item based on the key function. In this case you can use itemgetter(-1) in order to get the max item based on intended index then since the max() function returns the whole item from your list (sub-list) you can get the expected item by indexing:
>>> from operator import itemgetter
>>> max(lst, key=itemgetter(-1))[-1]
3
Or more functional:
>>> key_func = itemgetter(-1)
>>> key_func(max(lst, key=key_func))
3
applying max on the list will return the maximum list, which isn't what you want. You could indeed use a list comprehension to extract the third element, and then apply max on that comprehension:
>>> lst = [[1, 2, 3], [2, 4, 2], [0, 1, 1]]
>>> max([x[2] for x in lst])
3

Append elements of a set to a list in Python

How do you append the elements of a set to a list in Python in the most succinct way?
>>> a = [1,2]
>>> b = set([3,4])
>>> a.append(list(b))
>>> a
[1, 2, [3, 4]]
But what I want is:
[1, 2, 3, 4]
Use
a.extend(list(b))
or even easier
a.extend(b)
instead.
You could use extend as already pointed out, but there's also a more concise approach:
>>> a += b
>>> a
[1, 2, 3, 4]
If you want to update the list, this works for me:
a += b
If you want a non-mutating expression:
a + list(b)

Categories