String基于某些格式排序

时间:2010-12-19 10:09:56

标签: python string sorting

我有一个字符串需要根据sort_fmt进行排序。例如:如果字符串是'abdcdfs'& sort_fmt是'dacg'。排序后,输出应为'ddacfbs'。如您所见,输入字符串中可能存在字符串中不存在的字符,反之亦然。输入字符串中不存在于订单字符串中的字符应以任何顺序出现在输出字符串的末尾。

这是我写的。它有效,它是O(n * m)算法。我想知道是否有更好的&更短的方法吗?也许使用itertools

def sort_str(s, sort_fmt):
    sorted_str = ''
    str_hash   = dict()

    # O(n)
    for ch in s:
        if ch in str_hash:
            str_hash[ch] += 1
        else:
            str_hash[ch] = 1

    # O(m) + O(1) where m<=n
    for ch in sort_fmt:
        if ch in str_hash:
            cnt = str_hash[ch]
            sorted_str += cnt * ch

    # O(n)
    for ch in s:
        if ch not in sort_fmt:
            sorted_str += ch
    return sorted_str


if __name__ == '__main__':
    print sort_str('abdcdfs', 'dacg')

2 个答案:

答案 0 :(得分:6)

您正在尝试实施counting sort,在某些条件下确实是O(n)。但是,您的实现在结尾附近有两个错误,这意味着您的实现的实际时间复杂度为O(n 2 + n * m):

for ch in s:
    if ch not in sort_fmt:  # <--- "in" requires a linear search. O(n*m)
        sorted_str += ch    # <--- Ouch! Concatenation! O(n^2)
  • 您正在以低效的方式构造结果,因为您在循环中使用连接。
  • 在字符串上使用in在字符串的长度上是线性的,并且您是在循环中执行此操作。

试试这个。由于collections.Counter的使用,它需要Python 2.7或更高版本,但对于旧版本的Python,Counter可以很容易地替换为defaultdict

from collections import Counter

def sort_str(s, sort_fmt):
    counter = Counter(s)
    d = set(sort_fmt)
    result = ''.join(c * counter[c] for c in sort_fmt)
    result += ''.join(c for c in s if c not in d)
    return result

if __name__ == '__main__':
    print sort_str('abdcdfs', 'dacg')

如果您放弃了应该为O(n)的要求,这是获得所需结果的更简洁方法:

>>> d = dict((v,k) for (k,v) in enumerate('dacg'))
>>> sorted('abdcdfs', key = lambda c:d.get(c, len(d)))
['d', 'd', 'a', 'c', 'b', 'f', 's']

答案 1 :(得分:0)

我不确定排序的复杂性。这工作

def sort_str(s, frmt):
    l = len(frmt)
    return sorted(s, key = lambda x: frmt.index(x) if x in frmt else l)