Posts: 82
Threads: 11
Joined: Sep 2016
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?
Posts: 7,313
Threads: 123
Joined: Sep 2016
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
Posts: 82
Threads: 11
Joined: Sep 2016
(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.
Posts: 7,313
Threads: 123
Joined: Sep 2016
What have you tried?
Post working code,can not run what you have in first post.
Posts: 687
Threads: 37
Joined: Sep 2016
Feb-06-2017, 06:40 PM
(This post was last modified: Feb-06-2017, 06:41 PM by Ofnuts.)
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
Posts: 2,953
Threads: 48
Joined: Sep 2016
itemgetter() could be faster
Posts: 7,313
Threads: 123
Joined: Sep 2016
(Feb-06-2017, 06:41 PM)wavic Wrote: itemgetter() could be faster No,you are guessing again
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))
Posts: 82
Threads: 11
Joined: Sep 2016
(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?
Posts: 687
Threads: 37
Joined: Sep 2016
Feb-06-2017, 08:32 PM
(This post was last modified: Feb-06-2017, 08:32 PM by Ofnuts.)
(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
Posts: 3,458
Threads: 101
Joined: Sep 2016
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']
|