Problem Statement: I have a dictioary where values are many different type like int, str, list, class, class atrribute, class method etc. I want to do value sorting by type
. Like string, list, would be first and then rest.,
Can someone suggest how to write a key function so that I can control sorting by type
class dummy:
a = 1
obj = dummy()
x = {'b':1,'a':'abc','c':obj, 'd':obj.a, 'e': [1,2,3]}
x = dict(sorted(x.items() , key = lambda x:type(x[1]))) #It will fail as can't compare the type
print(x)
Expcted output:
print(x)
{'a':'abc','e': [1,2,3] ,'c':obj, 'd':obj.a, 'b':1}
CodePudding user response:
There is probably a better way to do this, but this example works:
>>> maps = {
'str': 0,
'list': 1,
'int': 2,
'dummy': 3
}
>>> dict(sorted(x.items(), key=lambda x: maps.get(type(x[1]).__name__, 999)))
{'a': 'abc', 'e': [1, 2, 3], 'b': 1, 'd': 1, 'c': <__main__.dummy object at 0x000001C1FEB8B250>}
alternative (the same, but lambda
is replaced with a full fledged function):
>>> maps = {
'str': 0,
'list': 1,
'int': 2,
'dummy': 3
}
>>> def sort_key(x):
value = x[1]
map_key = type(value).__name__
return maps.get(map_key, 999)
>>> dict(sorted(x.items(), key=sort_key))
{'a': 'abc', 'e': [1, 2, 3], 'b': 1, 'd': 1, 'c': <__main__.dummy object at 0x000001BE86F8BB50>}
CodePudding user response:
As the key to the sorted
function, I suggest this function:
lambda x: (not isinstance(x[1], str), not isinstance(x[1], list), type(x[1]).__name__)
This will map values as follows:
- strings to the tuple
(False, True, 'str')
; - lists to the tuple
(True, False, 'list')
; - other objects to a tuple
(True, True, 'something else')
.
Since tuples are sorted in lexicographical order, and False < True
, this will put strings first, lists second, and values of other types will be sorted in alphabetical order of the name of the type.
With the example data provided in your question:
class dummy:
a = 1
obj = dummy()
d = {'b':1,'a':'abc','c':obj, 'd':obj.a, 'e': [1,2,3]}
d = dict(sorted(d.items() , key = lambda x: (not isinstance(x[1], str), not isinstance(x[1], list), type(x[1]).__name__)))
print(d)
{'a': 'abc', # (False, True, 'str')
'e': [1, 2, 3], # (True, False, 'list')
'c': <__main__.dummy object at 0x10f311ba8>, # (True, True, 'dummy')
'b': 1, # (True, True, 'int')
'd': 1 # (True, True, 'int')
}
CodePudding user response:
I think you can use str convertion:
class dummy:
a = 1
obj = dummy()
x = {'b':1,'a':'abc','c':obj, 'd':obj.a, 'e': [1,2,3]}
x = dict(sorted(x.items() , key = lambda x:str(type(x[1])))) #It will fail as can't compare the type
print(x)