首页 > 解决方案 > 将排序的字符聚集在一起的更优雅的方式?

问题描述

假设,我想按频率对字符串中的字符进行排序。

def frequencySort(self, s: str) -> str:
    
    freq = {}
    
    for i in s:
        if i in freq:
            freq[i] += 1
        else:
            freq[i] = 1
    
    print(freq)
    
    sorted_chars = sorted(s, key = lambda x : -freq[x])
    
    return "".join(sorted_chars)

但是,对于某些字符具有相同频率的输入,这些字符最终会在输出中混合在一起。

例如,对于输入loveleetcode输出上面的代码,eeeelolovtcd它应该输出eeeeoollvtcdeeeelloovtcd(o 和 l 应该聚集在一起,而不是混合)。

因此,我添加了一个使用字符 ASCII 代码的一小部分的决胜局(最终小于一个,因此保证不会压倒下一个最常见的字符):

def frequencySort(self, s: str) -> str:
    
    freq = {}
    
    for i in s:
        if i in freq:
            freq[i] += 1
        else:
            freq[i] = 1
    
    # Tie-breaker:
    
    for i in freq:
        freq[i] += ord(i) / 1000
    
    sorted_chars = sorted(s, key = lambda x : -freq[x])
    
    return "".join(sorted_chars)

这很好用,但我想知道是否有更优雅(pythonic)的方式来在排序过程中强制对相似字符进行聚类。

标签: pythonsorting

解决方案


将排序键更改为包含字符本身的元组。

def frequencySort(self, s: str) -> str:
    freq = {}
    for i in s:
        if i in freq:
            freq[i] += 1
        else:
            freq[i] = 1
    
    sorted_chars = sorted(s, key=lambda x: (-freq[x], x))
    return "".join(sorted_chars)

现在,当sorted()遇到两个具有相同计数的不同字符时,它将使用元组的下一个元素对它们进行排序。由于下一个元素是字符本身,因此相同的字符将彼此相邻排序。

>>> solution.frequencySort("loveleetcode")
'eeeelloocdtv'

无关说明:您可以使用collections.Counter而不是创建字典并计算字符。

freq = collections.Counter(s)

代替

freq = {}
for i in s:
    if i in freq:
        freq[i] += 1
    else:
        freq[i] = 1

推荐阅读