I have some custom objects and dictionaries that I want to sort. I want to sort both the objects the dictionaries together. I want to sort the objects by an at开发者_JS百科tribute and the dictionaries by a key.
object.name = 'Jack'
d = {'name':'Jill'}
sort_me =[object, d]
How do I sort this list using the object's name attribute and the dictionary's 'name' key?
What you are almost certainly looking for is to use the key= option for sorted(), which provides a function which returns an arbitrary sort key for each element. This function can check the type of its argument and take various actions. For instance:
import types
class obj(object):
def __init__(self, arg):
self.name = arg
def extract_name(obj):
if type(obj) is types.DictType:
return obj['name']
else:
return obj.__dict__['name']
d = { 'name': 'Jill'}
print sorted([obj('Jack'), d], key=extract_name)
More information can be found on the Python wiki
RichieHindle's suggestion of using isinstance is a good one. And while I was at it I thought it might be nice to support arbitrary element names instead of hardcoding 'name':
def extract_elem_v2(elem_name):
def key_extractor(obj):
dct = obj if isinstance(obj, dict) else obj.__dict__
return dct[elem_name]
return key_extractor
Which you can use like so:
print sorted(list_of_stuff, key=extract_elem_v2('name'))
sort_me.sort(key=attr_or_itemgetter('name'))
Where attr_or_itemgetter()
:
class attr_or_itemgetter(object):
def __init__(self, name):
self.name = name
def __call__(self, obj):
try: return getattr(obj, name)
except AttributeError:
return obj[name]
NOTE: It intentionally doesn't check for dictionary type, therefore attr_or_itemgetter('items')
applied to a dictionary will return dict.items
method.
This worked for me. Note that sort()
does not return the sorted list, but sorted()
does, so if you want to pass this to a template, you should use sorted
in the parameters, or sort
before you pass the list as a parameter.
itemized_action_list = list(chain(detection_point.insertbodyaction_set.all(),
detection_point.insertheaderaction_set.all(),
detection_point.modifybodyaction_set.all(),
detection_point.modifyheaderaction_set.all(),
detection_point.removebodyaction_set.all(),
detection_point.removeheaderaction_set.all(),
detection_point.redirectaction_set.all()))
sorted(itemized_action_list, key=attrgetter('priority'))
new_list = [10,"m",20,30,"a","r",70,"d"]
def func(x):
if type(x) == str:
return ord(x)+100
return x
new_list.sort(key=func)
print(new_list)
[10, 20, 30, 70, 'a', 'd', 'm', 'r']
精彩评论