2

I am trying to sort the string 'sOrTiNg1234' in the order lowercase-->uppercase-->nums

I did

string = sorted(input(), key = lambda c: (c.isdigit(), c.isupper(),c.islower()))

I had to do the keys as to what seemed right. For example, I first wanted to check if it was a letter or not, and then I wanted to check if it was lower case, and then check if it was uppercase. However, the exact opposite seemed to work.

Could somebody explain how exactly the keys work with sorted?

Thanks a bunch

3
  • 2
    False < True. Commented Jun 14, 2017 at 3:56
  • @user2357112 That can be simplified to True. Commented Jun 14, 2017 at 3:57
  • @user2357112 Ah, that makes sense. Thanks Commented Jun 14, 2017 at 3:59

2 Answers 2

3

As briefly hinted in comments, the problem is that True == 1 and False == 0, and thus True is actually sorted after False. So if you put the keys in the "intuitive" order, you get this:

>>> s = 'sOrTiNg1234'
>>> sorted(s, key = lambda c: (c.islower(), c.isupper(), c.isdigit()))
['1', '2', '3', '4', 'O', 'T', 'N', 's', 'r', 'i', 'g']

This might become a bit clearer by having a look at the key tuples:

>>> [(c, map(int, (c.islower(), c.isupper(), c.isdigit()))) for c in s]
[('s', [1, 0, 0]),
 ('O', [0, 1, 0]),
 ('r', [1, 0, 0]),
 ('T', [0, 1, 0]),
 ('i', [1, 0, 0]),
 ('N', [0, 1, 0]),
 ('g', [1, 0, 0]),
 ('1', [0, 0, 1]),
 ('2', [0, 0, 1]),
 ('3', [0, 0, 1]),
 ('4', [0, 0, 1])]

You can fix this by using the reverse parameter:

>>> sorted(s, key = lambda c: (c.islower(), c.isupper(), c.isdigit()), reverse=True)
['s', 'r', 'i', 'g', 'O', 'T', 'N', '1', '2', '3', '4']

Or, as you did, by reversing the values in the key tuple:

>>> sorted(s, key = lambda c: (c.isdigit(), c.isupper(), c.islower()))
['s', 'r', 'i', 'g', 'O', 'T', 'N', '1', '2', '3', '4']

Or by negating the individual keys (not works, too):

sorted(s, key = lambda c: (-c.islower(), -c.isupper(), -c.isdigit()))
['s', 'r', 'i', 'g', 'O', 'T', 'N', '1', '2', '3', '4']

Also note that using lower and upper is actually redundant:

>>> sorted(s, key = lambda c: (c.isdigit(), c.isupper()))
['s', 'r', 'i', 'g', 'O', 'T', 'N', '1', '2', '3', '4']

And if you also want to sort by the character itself, add it at the end of the tuple:

>>> sorted(s, key = lambda c: (c.isdigit(), c.isupper(), c))
['g', 'i', 'r', 's', 'N', 'O', 'T', '1', '2', '3', '4']
Sign up to request clarification or add additional context in comments.

1 Comment

as you mentioned c.islower() is redundant and the expression sorted(s, key = lambda c: (c.isdigit(), c.isupper(), c)) is OK
0

What I had done is that I mapped all the alphanumerical characters to somenumbers

The smaller case alphabets are mapped from 0 to 25 by subtracting 97 from the ascii value of smaller case alphabets.

Similarly larger case alphabets are mapped from 26 to 51 by subtracting 65(ord('A')) and adding 26 from the ascii value of smaller case alphabets.

similarly numeric values are mapped from 52 to 61 by subtracting 48(ord('0') from ascii value of numeric characters

Afterr doing all this each character points to somenumber. And all the characters are sorted according to those numbers.And finally after sorting the list I joined all the characters

def function(alpha) : 

    if alpha.islower():
        return ord(alpha)-97  #from a(0) to z(25) 
    elif alpha.isupper():
        return ord(alpha)-65+(26)  #from A(26)  to Z(51)
    else:
        return ord(alpha)-48+(52)   #from 0(52)  to 9(61)
x="sOrTiNg1234"

y=list(x)      

y=sorted(y,key=function)

answer=''.join(y)

I hope that it makes sense :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.