我有一个对象列表。每个对象都有两个属性:DispName
和MachID
。 DispName
可以以theoretical
开头,也可以是其他内容。
我需要按以下方式对此列表进行排序:
MachID
按字母顺序排列。
MachID
子组中,首先是名称以theoretical
这是我现在的代码,它可以工作并产生所需的输出,但是我想知道我是否可以编写更多的pythonic,也许可以使用groupby
? (我为camelCasing的借口)。
from collections import defaultdict, namedtuple
from operator import attrgetter
Mapping = namedtuple('Mapping', ['DispName', 'MachID'])
objectList = [Mapping('map 2 (MT1)', 'MT1'),
Mapping('theoretical (MT1)', 'MT1'),
Mapping('map 3 (MT2)', 'MT2'),
Mapping('theoretical (MT2)', 'MT2'),
Mapping('map 1 (MT1)', 'MT1'),
Mapping('map 2 (MT2)', 'MT2')]
def complexSort(objectList):
objectDict = defaultdict(list)
sortedMappingList = []
# group by machine ID
for obj in objectList:
objectDict[obj.MachID].append(obj)
# loop over the mappings sorted alphabetically by machine ID
for machID in sorted(objectDict.keys()):
mappings = objectDict[machID]
nonTheoreticalMappings = []
for mapping in mappings:
if mapping.DispName.startswith('theoretical'):
# if we encounter the theoretical mapping, add it first
sortedMappingList.append(mapping)
else:
# gather the other mappings in a sublist
nonTheoreticalMappings.append(mapping)
# and add that sublist sorted alphabetically
sortedMappingList.extend(sorted(nonTheoreticalMappings,
key=attrgetter('DispName')))
return sortedMappingList
for mapping in complexSort(objectList):
print mapping.DispName
产地:
theoretical (MT1)
map 1 (MT1)
map 2 (MT1)
theoretical (MT2)
map 2 (MT2)
map 3 (MT2)
答案 0 :(得分:3)
只需使用sorted
与key
生成您想要的订单。由于元组按字典顺序排序,产生元组的key
应该可以很好地工作。
def sort_key(thing):
return (thing.MachID, not thing.DispName.startswith('theoretical'))
sorted(objectList, key=sort_key) # returns a list sorted the way you want
答案 1 :(得分:2)
import collections
import operator
import itertools as IT
Mapping = collections.namedtuple('Mapping', ['DispName', 'MachID'])
objectList = [Mapping('map 2 (MT1)', 'MT1'),
Mapping('theoretical (MT1)', 'MT1'),
Mapping('map 3 (MT2)', 'MT2'),
Mapping('theoretical (MT2)', 'MT2'),
Mapping('map 1 (MT1)', 'MT1'),
Mapping('map 2 (MT2)', 'MT2')]
sortedMappingList = sorted(objectList,
key=lambda mapping:
(mapping.MachID,
not mapping.DispName.startswith('theoretical'),
mapping.DispName))
for key, group in IT.groupby(sortedMappingList, key=operator.attrgetter('MachID')):
for g in group:
print(g.DispName)
产量
theoretical (MT1)
map 1 (MT1)
map 2 (MT1)
theoretical (MT2)
map 2 (MT2)
map 3 (MT2)
这里有How to sort using key functions的优秀教程。
答案 2 :(得分:1)
您可以创建一个自定义比较器来描述两个映射应该如何相互排序。这比你的complexSort
更干净,因为函数唯一的责任是比较两个对象,并将实际的排序留给Python。
from collections import namedtuple
Mapping = namedtuple('Mapping', ['DispName', 'MachID'])
def cmp_Mapping(a,b):
#first, sort alphabetically by MachID
if a.MachID != b.MachID:
return cmp(a.MachID, b.MachID)
else:
#if MachIDs match, and one starts with "theoretical", it should go first.
if a.DispName.startswith("theoretical") and not b.DispName.startswith("theoretical"):
return -1
elif b.DispName.startswith("theoretical") and not a.DispName.startswith("theoretical"):
return 1
#everything else is ordered alphabetically.
else:
return cmp(a.DispName, b.DispName)
objectList = [Mapping('map 2 (MT1)', 'MT1'),
Mapping('theoretical (MT1)', 'MT1'),
Mapping('map 3 (MT2)', 'MT2'),
Mapping('theoretical (MT2)', 'MT2'),
Mapping('map 1 (MT1)', 'MT1'),
Mapping('map 2 (MT2)', 'MT2')]
for mapping in sorted(objectList, cmp = cmp_Mapping):
print mapping.DispName
结果:
theoretical (MT1)
map 1 (MT1)
map 2 (MT1)
theoretical (MT2)
map 2 (MT2)
map 3 (MT2)