问题描述
|
假设我有一个这样的列表/元组:
MyLocation = \'DE\'
(
(\'Pencils\',\'Artists Pencils\',18.95,\'PVT\',\'DE\'),(\'Pencils\',\'\',19.95,\'IT\'),23.50,\'PRF1\',\'US\'),\'Wooden Pencils\',\'PRF2\',12.50,\'NON\',\'DE\'))
我想按照以下规则分两遍进行排序:
1)在the2ѭ元素中匹配MyLocation字符串\'DE\'
的元组
这是中间步骤,ѭ3之间的相对顺序无关紧要。只是为了使所有ѭ3都位于顶部。
(
(\'Pencils\',\'IT\')
)
2)之后,对第6个元素进行排序,首选顺序应为第7个。其他字符串可以留在较低位置。
我期望的最终排序输出是
(
(\'Pencils\',\'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
我对如何进行第二种排序感到特别困惑。请提供代码样本以进行第二次排序。
解决方法
总体思路是给每个项目打分。如果每个项目有多个分数,则可以将其放入元组。
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,\'IT\'),23.50,\'PRF1\',\'US\'),\'Wooden Pencils\',\'PRF2\',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)
),但另一方面,可以轻松地以这种方式扩展。
,这就够了:
PRF = (\'PRF1\',\'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\',... (\'Pencils\',\'DE\') )
>>> import pprint
>>> pprint.pprint(sorted(records,key=k))
[(\'Pencils\',23.5,12.5,\'IT\')]
,您只需通过一次,即可使用特殊的按键功能。
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)
键函数返回一个值,该值将用于比较列表中的元素。这个返回一个由两个元素组成的元组,并且元组根据最早的不同元素进行比较。所以(1,0) < (2,-300)
因为1 <2
第一个值是列表[\'PRF1\',\'PRF3\']
中的索引t[3]
或如果不是索引号3,则为数字3。这意味着它在列表中越早,值越低,并且排序结果越早。第二个值已在注释中说明。 :)
,这有点棘手,但应该这样做。
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
开始;然后ѭ22会按照编号在彼此之间排序。