假设我有一个像这样的列表/元组:
MyLocation = 'DE'
(
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
('Pencils', '', 19.95, 'PVT', 'IT'),
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', '', 12.50, 'NON', 'DE'))
我希望按照以下规则分两次进行排序:
1)匹配'DE'
元素中MyLocation字符串[4]
的元组,位于顶部
这是一个中间步骤,DE
之间的相对顺序无关紧要。这样所有DE
都位于顶部。
(
('Pencils', '', 12.50, 'NON', 'DE'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', '', 19.95, 'PVT', 'IT')
)
2)之后,对[3]
rd元素进行排序,首选顺序应为['PRF1', 'PRF2', 'PRF3']
。其他字符串可以留在较低的位置。
我预期的最终排序输出是
(
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
('Pencils', '', 12.50, 'NON', 'DE'),
('Pencils', '', 19.95, 'PVT', 'IT')
)
我怎么去这两种?我可以用del和insert来管理第一个排序,但建议的方法是什么?
tempList = actualList
i = 0
for record in actualList:
if record[5] == 'DE':
del tempList[i]
tempList.insert(0, record)
i = i + 1
actualList = tempList
我对如何进行第二次排序感到特别困惑。请提供第二次排序的代码示例。
答案 0 :(得分:2)
这就够了:
PRF = ('PRF1', 'PRF2', 'PRF3')
sorted(records, key=lambda x:(x[4]!='DE', PRF.index(x[3]) if x[3] in PRF else 3))
或者如果你要使用它,那么一旦你想分开关键功能:
k = lambda x: (x[4]!='DE', PRF.index(x[3]) if x[3] in PRF else len(PRF))
然后只需使用
sorted(records, key=k)
在你的例子中:
>>> records = ( ('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
... ('Pencils', '', 19.95, 'PVT', 'IT'),
... ('Pencils', '', 23.50, 'PRF1', 'US'),
... ('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
... ('Pencils', '', 12.50, 'NON', 'DE') )
>>> import pprint
>>> pprint.pprint(sorted(records, key=k))
[('Pencils', 'Wooden Pencils', 23.5, 'PRF2', 'DE'),
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
('Pencils', '', 12.5, 'NON', 'DE'),
('Pencils', '', 23.5, 'PRF1', 'US'),
('Pencils', '', 19.95, 'PVT', 'IT')]
答案 1 :(得分:1)
您只需要一次通过,具有特殊的按键功能。
def key(t):
return (
dict(PRF1=0, PRF2=1, PRF3=2).get(t[3], 3), # earlier ones get smaller numbers
int(t[4] != 'DE')) # 0 if DE, 1 otherwise
L.sort(key=key)
key函数返回一个值,用于比较列表中的元素。这个返回一个由两个元素组成的元组,元组根据最早的不同元素进行比较。所以(1, 0) < (2, -300)
因为1&lt; 2。
第一个值是列表t[3]
中的['PRF1', 'PRF2', 'PRF3']
索引或第3个值(如果不是这些索引)。这意味着列表中较早的值,值越低,排序结果中越早。第二个值已在注释中说明。 :)
答案 2 :(得分:1)
一般的想法是给每个项目一个分数。如果每个项目有多个分数,则可以将其放入元组中。
MyLocation = 'DE'
location_score = { MyLocation : 1 }
that_other_field_score = {'PRF1' : 3, 'PRF2' : 2, 'PRF3' : 1}
def score( row ):
# returns a tuple of item score
# items not in the score dicts get score 0 for that field
return ( that_other_field_score.get(row[3], 0),
location_score.get(row[4], 0))
data = [
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
('Pencils', '', 19.95, 'PVT', 'IT'),
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', '', 12.50, 'NON', 'DE')]
# sort data, highest score first
data.sort(key=score, reverse=True)
print data
location_score
dict可能有点矫枉过正(你可以写(1 if row[4]=='DE' else 0)
)但另一方面它可以通过这种方式轻松扩展。
答案 3 :(得分:0)
这有点苛刻,但应该这样做。
def prf_key(item):
if item[3][:3] == 'PRF':
return (0, int(item[3:]))
else:
return (1, None)
actualList.sort(key = prf_key)
我们的想法是,任何PRF
都应该排在最前面,因此它会返回一个以0
开头的元组,其余为1
;然后PRF
按照他们的号码排序。