假设我想按字母顺序对一系列名称进行排序,但还有一个额外的规则:
如果以下列表中有任何名称:
Mike Cathy James Albert Austin
出现后,它们将被移动到序列的 head ,并被排序为Mike -> Cathy -> James -> Albert -> Austin
。
例如,如果原始序列是这样的:
Conan,Cary,Clarence,Cathy,Mike,Blake,Baron,Vaughan,Albert,Gabriel,Cathy
期望的结果是:
Mike,Cathy,Cathy,Albert, Baron,Blake,Cary,Clarence,Conan,Gabriel,Vaughan
注意Mike, Cathy and Albert
不再按字母顺序排序,它们作为一个整体先于其他常用名称,并具有自己的预定义顺序。
我的问题有一些进一步的解释:
有谁能告诉我如何以快速/有效的方式实现这一目标?
答案 0 :(得分:4)
一种方法:
该方法应该适用于任何具有排序和列表或数组的语言来保存名称。
在Python中:
names=['Conan', 'Cary', 'Clarence', 'Cathy', 'Mike', 'Blake', 'Baron', 'Vaughan', 'Albert', 'Gabriel', 'Cathy']
specials=['Mike', 'Cathy', 'James', 'Albert', 'Austin']
# split the lists.
n1=[n for n in names if n in specials] # ifilter would also work in Python
n2=[n for n in names if n not in specials]
# sort the first list based on order of specials, second lexicographically and combine:
print sorted(n1, key=lambda n:specials.index(n))+sorted(n2)
打印:
['Mike', 'Cathy', 'Cathy', 'Albert', 'Baron', 'Blake', 'Cary', 'Clarence', 'Conan', 'Gabriel', 'Vaughan']
改进是:
cmp
函数对列表/数组进行排序。在Python中,您将在键功能中使用元组。在C中,您将编写自定义cmp函数。有了它,您可以根据语言的功能对names
进行排序。
元组中的两个元素将是特殊项中名称的否定索引(根据零基础索引进行调整),然后是名称。如果非零,则元组的第一个元素将胜过第二个元素。由于第一个元素是一个整数,即使specials
中有超过10个名称,它也会正确排序。
再次,在Python中:
def cf(n):
rtr=(specials.index(n)-len(specials)-1 if n in specials else 0, n)
print rtr # to show what is being generated for the sort key...
return rtr
names.sort(key=cf) # sorts inplace
打印:
(0, 'Conan')
(0, 'Cary')
(0, 'Clarence')
(-5, 'Cathy')
(-6, 'Mike')
(0, 'Blake')
(0, 'Baron')
(0, 'Vaughan')
(-3, 'Albert')
(0, 'Gabriel')
(-5, 'Cathy')
现在names
已按原样排序并一次性传递到:
['Mike', 'Cathy', 'Cathy', 'Albert', 'Baron', 'Blake', 'Cary', 'Clarence', 'Conan', 'Gabriel', 'Vaughan']
答案 1 :(得分:1)
对于几乎任何软排序特殊情况,一个技巧是将元素转换为“按键”,按照您想要的方式排序,进行常规排序,然后将它们转换回来。
例如,
某些语言或库(如C或C ++)可以覆盖比较。这对于简单的案例来说是有用的(也是有效的)。其他语言(如Python)可以按需提供排序键,这使得这种方法非常简单。
如果我记得,Knuth在 TAoCP 中有一个这种方法的例子。在那一个中,他有书名,排序规则就像是盲目的,将'A'和'the'移到标题的末尾等等。
答案 2 :(得分:0)
所以我的算法将是伪代码中的以下算法。
输入:字符串的向量V,字符串的侦听L(例外情况),与L
关联的顺序Let pivot be a random element of V
Let A,B,C be three empty arrays of strings
For name in V
if (name in L)
add name to A
else if (name <= pivot) // for the lexicographic order
add name to B
else if (name > pivot) // for the lexicographic order
add name to C
If (pivot in L)
add pivot to A
Else
add pivot to B
Sort A for the order associated with L
Sort B for the lexicographic order
Sort C for the lexicographic order
Merge B in A
Merge C in A
Return A