简体   繁体   中英

sorting keys of a dictionary with lowercase letters, uppercase letters and numbers

I want to sort the keys of a dictionary first by numbers then lowercase letters and then uppercase letter and return it back in a dictionary with the correct value for the key. I came up with this, but in my opinion this is too long. (board is the given dictionary you want to sort) board example :

board = {
  (3, 4) : 0,
  ("a", 4) : 0,
  (1, 3)  :  0,
  ("X", 5) : 5,
  ("X", 1) : 1
}

My question is if it is possible to shorten the code.

x = []
y = []
for k in dict.keys(board):
    if str(k[0]).islower():
        list.append(x, (k, board[k]))
for k in dict.keys(board):
    if k[0] == "X":
        list.append(y, (k, board[k]))
for k in range(0, len(x)):
    del board[x[k][0]]
for k in range(0, len(y)):
    del board[y[k][0]]
x = sorted(x)
y = sorted(y)
for k in range(0, len(x)):
    board[x[k][0]] = x[k][1]
for k in range(0, len(y)):
    board[y[k][0]] = y[k][1]

Following sort based in desired order but based upon the key tuple.

Thus ('X', 1) should be before ('X', 5) because first elements are equal so depends on second element.

Sort Routine

def sort_dict(d):
  def ordering(i):
    """Create ordering so that numbers are before strings
       lowercase strings are before upper case strings"""
    return ([isinstance(i, int), isinstance(i, str) and i.islower(), isinstance(i, str) and i.isupper()].index(True), i)

  # By applying ordering to all elements of key, we create a new tuple
  # which allows us to compare
  return dict(sorted(d.items(), key=lambda kv: tuple(map(ordering, kv[0]))))

Test

board =  {(3,4):0,("a",4):0,(1,3):0,("X",5):5,("X",1):1}
print(sort_dict(board))

Output

{(1, 3): 0, (3, 4): 0, ('a', 4): 0, ('X', 1): 1, ('X', 5): 5}

You can maybe do something like this:

result = {}
for x in sorted(filter(lambda x: type(x[0]) == int, board.keys())):
  result[x] = board[x]

for x in sorted(filter(lambda x: type(x[0]) == str, board.keys()), key=lambda x: x[0].islower(), reverse=True):
  result[x] = board[x]

>>> result
{(1, 3): 0, (3, 4): 0, ('a', 4): 0, ('X', 5): 5, ('X', 1): 1}

Also, just in case if you wanted to have uppercase letters before lowercase and if the numbers were only 1 digit long then you could have used ord to sort them

>>>sorted(board.keys(), key=lambda x: ord(str(x[0])) if type(x[0]) == int else ord(x[0]))
[(1, 3), (3, 4), ('X', 5), ('X', 1), ('a', 4)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM