Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
lists.sort() with cmp
#1
I wonder how to make sorting with 'cmp' work in Python 2.7.

It's not my case, but as an example, how could I sort sets like
[Wednesday, Tuesday, Saturday, Monday, Sunday], [Monday, Tuesday, Friday, Wednesday], 
[Sunday, Saturday, Sunday], [Friday, Tuesday, Thursday]
 
in the weekdays order?
Obviously, I can't sort them alphabetically or by word length. I need to give an order in the kind of Monday < Tuesday < Wednesday < Thursday < Friday < Saturday < Sunday.

The python docs write: "cmp specifies a custom comparison function of two arguments (list items) which should return a negative, zero or positive number depending on whether the first argument is considered smaller than, equal to, or larger than the second argument: cmp=lambda x,y: cmp(x.lower(), y.lower())." Now I have more then two arguments (in the weekdays example, there are 7), and I would prefer a way without lambda, if that's possible. I seem to remember that a function could be used?
Reply
#2
cmp is is removed in Python 3.
Quote:The cmp() function should be treated as gone, and the __cmp__() special method is no longer supported.
So it was a bad idea,and key=somthing is better and works also fine in Python 2.7.
Quote:and I would prefer a way without lambda, if that's possible. I seem to remember that a function could be used?
You can import itemgetter to avoid lambda.
But lambda is really nice with sorting:
>>> lst = [('Tom', 'C', 10), ('Kent', 'A', 12), ('Jenny', 'B', 15)]
>>> sorted(lst, key=lambda tup: tup[1])
[('Kent', 'A', 12), ('Jenny', 'B', 15), ('Tom', 'C', 10)]
Sorting middle elements to A,B,C.
Sorting HOW TO
Reply
#3
(Feb-06-2017, 05:26 PM)snippsat Wrote: cmp is is removed in Python 3.
I know. Therefore I explicitly stated that I am using Python 2.

And I know the SortingHowTo well. However, if it hides the answer to my question, it hides it very well. It describes what I already said that is useless in this case - sorting by word length, sorting by numbers... all this doesn't apply if I need to sort weekdays by their given order, not by their lexical strings.
Reply
#4
What have you tried?
Post working code,can not run what you have in first post.
Reply
#5
Your problem is defining what is a rather arbitrary sort order between some strings.
def compareWeekDays(d1,d2):
   days={'Sunday':0,'Monday':1,  'Saturday':7}
   return days[d1]-days[d2]
Of course the dictionary is a bit different if your first weekday is Monday.
Unless noted otherwise, code in my posts should be understood as "coding suggestions", and its use may require more neurones than the two necessary for Ctrl-C/Ctrl-V.
Your one-stop place for all your GIMP needs: gimp-forum.net
Reply
#6
itemgetter() could be faster
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#7
(Feb-06-2017, 06:41 PM)wavic Wrote: itemgetter() could be faster
No,you are guessing again Wink
You can test,timeit work fine.
lambda is a lot faster.
# Python 3.6
import timeit

_lambda = '''\
lst = [('Tom', 'C', 10), ('Kent', 'A', 12), ('Jenny', 'B', 15)]
sorted(lst, key=lambda tup: tup[1])
'''
#--> 18.7 sec

_itemgetter = '''\
from operator import itemgetter
lst = [('Tom', 'C', 10), ('Kent', 'A', 12), ('Jenny', 'B', 15)]
sorted(lst, key=itemgetter(1))
'''
#--> 33.8 sec

print(timeit.Timer(stmt=_lambda).timeit(number=10000000))
Reply
#8
(Feb-06-2017, 06:14 PM)snippsat Wrote: What have you tried?

I have tried to get a hint about how to build up a working code - as I had no idea how it should look like. All the things in the SortingHowTo give no (for me understandable) answer to that.

I mean, it's easy to say that
Monday = 'Monday'
Tuesday = 'Tuesday'
Wednesday = 'Wednesday'
Thursday = 'Thursday'
Friday = 'Friday'
Saturday = 'Saturday'
Sunday = 'Sunday'

list1 = [Wednesday, Tuesday, Saturday, Monday, Sunday]
list2 = [Monday, Tuesday, Friday, Wednesday]
list3 = [Sunday, Saturday, Sunday]
list4 = [Friday, Tuesday, Thursday]

list1.sort()
list2.sort()
list3.sort()
list4.sort()

print list1
print list2
print list3
print list4
only give the 'correct' result for list3 - and that's kind of 'accidentally' as in the case of Saturday and Sunday, the alphabetic order is the 'correct' one.


(Feb-06-2017, 06:40 PM)Ofnuts Wrote: Your problem is defining what is a rather arbitrary sort order between some strings.

And it becomes even much more 'arbitrary' when I leave the weekday example and go to what I wish, yes. But your code is exactly what I've been looking for, as far as I can say for the moment. I will try and see whether I can make my code working in that way.

My own approach was going to something like
def sortdays(day1, day2):
    if day1 == Monday and day2 == Tuesday:
        return -1
    elif day1 == Monday and day2 == Monday:
        return 0
    elif day1 == Tuesday and day2 == Monday:
        return 1
    elif day1 == Tuesday and day2 == Tuesday:
        return 0
    # and so on
but I had the notion (is that the right term?) that this probably is not the most efficient solution...

Then I came up with using a list, maybe like:
def sortdays(day1, day2):
    dayslist = [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
    if dayslist.index(day1) < dayslist.index(day2):
        return -1
    elif if dayslist.index(day1) == dayslist.index(day2):
        return 0
    else:
        return 1
But it seems not necessary that the results are only -1, 0 and 1? The subtraction will give results from -6 to 6?
Reply
#9
(Feb-06-2017, 08:09 PM)merl Wrote:
(Feb-06-2017, 06:40 PM)Ofnuts Wrote: Your problem is defining what is a rather arbitrary sort order between some strings.

And it becomes even much more 'arbitrary' when I leave the weekday example and go to what I wish, yes. But your code is exactly what I've been looking for, as far as I can say for the moment. I will try and see whether I can make my code working in that way.

My own approach was going to something like
def sortdays(day1, day2):
    if day1 == Monday and day2 == Tuesday:
        return -1
    elif day1 == Monday and day2 == Monday:
        return 0
    elif day1 == Tuesday and day2 == Monday:
        return 1
    elif day1 == Tuesday and day2 == Tuesday:
        return 0
    # and so on
but I had the notion (is that the right term?) that this probably is not the most efficient solution...

Then I came up with using a list, maybe like:
def sortdays(day1, day2):
    dayslist = [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
    if dayslist.index(day1) < dayslist.index(day2):
        return -1
    elif if dayslist.index(day1) == dayslist.index(day2):
        return 0
    else:
        return 1
But it seems not necessary that the results are only -1, 0 and 1? The subtraction will give results from -6 to 6?

Normally only the sign is important...  Retrieving something from a dictionary is normally faster than searching a list (but things can be different if the list is short).
Unless noted otherwise, code in my posts should be understood as "coding suggestions", and its use may require more neurones than the two necessary for Ctrl-C/Ctrl-V.
Your one-stop place for all your GIMP needs: gimp-forum.net
Reply
#10
But why are you trying to use cmp?  It was removed because it's bad.  You really don't want to be comparing every single pair against each other, that's slow.  If you just define a key, then that function will only be called once for each value to be sorted.  So...
>>> days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
>>> items = ["Monday", "Tuesday", "Friday", "Wednesday"]
>>> items.sort(key=lambda x: days.index(x))
>>> items
['Monday', 'Tuesday', 'Wednesday', 'Friday']
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Photo a.sort() == b.sort() all the time 3lnyn0 1 1,321 Apr-19-2022, 06:50 PM
Last Post: Gribouillis
  Sort List of Lists by Column Nju 1 11,459 Apr-13-2021, 11:59 PM
Last Post: bowlofred
  Split dict of lists into smaller dicts of lists. pcs3rd 3 2,378 Sep-19-2020, 09:12 AM
Last Post: ibreeden
  sort lists of lists with multiple criteria: similar values need to be treated equal stillsen 2 3,284 Mar-20-2019, 08:01 PM
Last Post: stillsen
  Creating new list from 2 lists after a custom sort pythoneer 12 6,057 Jun-01-2018, 04:55 PM
Last Post: pythoneer

Forum Jump:

User Panel Messages

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