Schwartzian transform(DSU)

  在了解python的时候发现Schwartzian transform这条规则,是针对computing intensive排序的一种高效手段,也被称作“装饰-排序-去装饰”(decorate-sort-undecorate),在Knuth的神作有详细介绍(当然我没有去翻)

  一般地,在python的排序中, 我们提供一个compare函数,然后交由python内建的sort处理,比如

 

def cmp(a,b):
    
if a>b:return 1
    
elif a<b:return -1
    
else:return 0

if __name__ == '__main__':
    ls 
= [1,8,5,3]
    ls.sort(cmp)
    
print ls

 你将会得到排好序的[1,3,5,8]

  但是,有时如果cmp过于复杂,直接这样做效率会很低,于是 Schwartzian transform这种最早出现在perl中的编程惯例便显现出优越性,它的主要思想是:

1. 对list中的复杂元素进行处理,提取出与排序相关的key,与原元素组合成为tupple

2.调用内建排序算法(对key)

3.提取出排好序的list

以下是伪代码:

def sortDSU(list)
    tmp 
= [(x.key(), x) for x in list] #这里key()表示提取排序相关的key值
    tmp.sort()  
    
return [x[1for x in tmp]

 

 当然如果你想实现in-place排序,最后一句换为

 

 list[:]= [x[1for x in tmp]

 ========================================================

总结:

DSU避免了对复杂元素反复计算key值,达到了memoization的效果

 

 最后,贴一个python cookbook上的例子:

Sorting a List of Objects by an Attribute of the Objects

 按照指定属性排序
def sort_by_attr(seq, attr):
    
import operator

    intermed 
= map(None, map(getattr, seq, (attr,)*len(seq)),
        xrange(len(seq)), seq)
    intermed.sort(  )
    
return map(operator.getitem, intermed, (-1,)*len(intermed))

如果对map不是很熟,另一种表述可能会更清晰

def sort_by_attr2(seq, attr):
    intermed 
= [(getattr(seq[i], attr), i, seq[i]) for i in xrange(len(seq))]
    intermed.sort(  )
    
return [ tup[-1for tup in intermed ]

 

 

posted @ 2009-11-14 16:38  xiaobenzhu  阅读(1266)  评论(1)    收藏  举报