Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
list sorting question
#1
I was checking up on sorting 2D lists, and found this (works fine):
#sort on first element
def takeFirst(elem):
    return elem[0]
# list
lst = [(2, 2), (3, 4), (4, 1), (1, 3)]
# sort 
lst.sort(key=takeFirst)
# print list
print('Sorted list:', lst)
At first i thought that takeFirst, takeSecond, were some kind of "reserved" words,
but when i replaced takeFirst with "chicken", it also worked !

Question: by what mechanism does takeFirst() know what "elem" is?

thx,
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#2
It appears that elem is a list datatype because it is iterable. The fact that you are identifying elements by position suggests to Python iterability, thus it attempts to reference it as such. Since takeFirst(...) is a function, the assumption is that elem is defined somewhere (by assignment) upon its first use as a variable before being passed.
Reply
#3
lists are referenced by index starting at 0 with syntax like list[index_number] or list[0].
elem[0] is equal to lst[0] or (2, 2).
Reply
#4
(Jun-17-2020, 09:22 AM)DPaul Wrote: Question: by what mechanism does takeFirst() know what "elem" is?

For each element in the list, the key-function is called with the element.

If your list is [(0,"A"), (1, "B"), (2, "C")], your key-function is called with:

key_func((0, "A"))
key_func((1, "B"))
key_func((2, "C"))

The key function could return a single comparable object or sequences (list, tuple, str).
If the key function return iterables, the different values must be comparable.
E.G. field1 of all elements must be comparable, field2 of all elements must be comparable and so far.

Calling the sorted function or inline sort method of list without a key-function, sorts iterables by first field, then by second and so far.

Now something which would fail:
my_list = [(0,"A"), (0, "B"), (0, 1)]
my_list.sort()
Error:
TypeError: '<' not supported between instances of 'int' and 'str'
And now a hidden error, which could appear:
my_list = [(0,"A"), (1, "B"), (2, 1)]
my_list.sort()
This code do not fail because Python don't check the second field, if the first field is unique.
But in the example before, all first fields had the same value. This is why the second field were checked and failed, because the last comparison was str vs int.

A helper function is operators.itemgetter, which is a callable, which return a new callable, which is the same as your key-function.

import operator

get_first = operator.itemgetter(0)
get_second = operator.itemgetter(1)

my_element = ["A", "B"]
print(get_first(my_element))
print(get_second(my_element))
Output:
A B
If you've instances of classes which do not support comparison and want to sort them by attributes, you can use the attrgetter from operator.
import random
import operator


# just a dummy class to demo
class Rand:
    def __init__(self):
        self.value = random.randint(0, 100)
    def __repr__(self):
        return f"Random {self.value}"
    __str__ = __repr__


rand_instances = [Rand() for _ in range(10)]
print("Original order:")
print(rand_instances)
print()

sorted_instances = sorted(rand_instances, key=operator.attrgetter("value"))
print(*sorted_instances, sep="\n")
Calling a plain sorted without key function on the list with the instances, will throw an Exception:
Error:
TypeError: '<' not supported between instances of 'Rand' and 'Rand'
I won't go further, just as a reference, you can implement comparison to a class:
https://docs.python.org/3.8/library/func...l_ordering
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
Thank you all for your elaborate answers.
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#6
(Jun-17-2020, 09:33 AM)kmzelikahle Wrote: The fact that you are identifying elements by position suggests to Python iterability

Actually, no. Sets and dictionaries are iterable but don't have a notion of position of elements. Iterable objects implement __iter__ (see the docs).
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  List Sorting Problem ZZTurn 5 1,281 Sep-22-2022, 11:23 PM
Last Post: ZZTurn
  Sorting List finndude 9 2,393 Jan-27-2022, 09:37 PM
Last Post: Pedroski55
  sorting a list of lists by an element leapcfm 3 1,807 Sep-10-2021, 03:33 PM
Last Post: leapcfm
  Sorting list of names using a lambda (PyBite #5) Drone4four 2 2,683 Oct-16-2020, 07:30 PM
Last Post: ndc85430
  sorting list of lists pframe 5 19,650 Apr-17-2020, 09:31 PM
Last Post: Larz60+
  sorting list arian29 2 2,102 Feb-02-2020, 10:31 AM
Last Post: ndc85430
  Converting parts of a list to int for sorting menator01 2 2,188 Nov-03-2019, 03:00 PM
Last Post: menator01
  Sorting a copied list is also sorting the original list ? SN_YAZER 3 2,996 Apr-11-2019, 05:10 PM
Last Post: SN_YAZER
  about List question longmail 2 2,319 Nov-30-2018, 02:08 AM
Last Post: longmail
  sorting a list of tuples based on date bluefrog 2 5,727 Aug-10-2018, 02:31 AM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020