【问题标题】:How to write a function that takes a string and prints the letters in decreasing order of frequency?如何编写一个接受字符串并按频率降序打印字母的函数?
【发布时间】:2009-03-20 12:32:19
【问题描述】:

我已经走到这一步了:

def most_frequent(string):
    d = dict()
    for key in string:
        if key not in d:
            d[key] = 1
        else:
            d[key] += 1
    return d

print most_frequent('aabbbc')

返回:

{'a': 2, 'c': 1, 'b': 3}

现在我需要:

  1. 反转对
  2. 按数字降序排序
  3. 只打印出字母

我应该将此字典转换为元组还是列表?

【问题讨论】:

  • 你想为'aabbbc'输出什么?我的猜测是“bbbaac”或“bac”
  • 好的,我在下面更新了我的答案

标签: python


【解决方案1】:

这是一个单行答案

sortedLetters = sorted(d.iteritems(), key=lambda (k,v): (v,k))

【讨论】:

  • 哇...非常好。我什至没有想过要寻找一个可以直接完成这项工作的内置!
  • 请注意,这里仍然需要反转。频率也需要修整。如果您导入 operator,您可以在一行中完成所有这些操作:map(operator.itemgetter(0), sorted(d.iteritems(), key=operator.itemgetter(1), reverse=True))。
  • @Stephan:添加你自己的帖子让我投票如何?
【解决方案2】:

这应该做得很好。

def frequency_analysis(string):
    d = dict()
    for key in string:
        d[key] = d.get(key, 0) + 1
    return d

def letters_in_order_of_frequency(string):
    frequencies = frequency_analysis(string)
    # frequencies is of bounded size because number of letters is bounded by the dictionary, not the input size 
    frequency_list = [(freq, letter) for (letter, freq) in frequencies.iteritems()]
    frequency_list.sort(reverse=True)
    return [letter for freq, letter in frequency_list]

string = 'aabbbc'
print letters_in_order_of_frequency(string)

【讨论】:

    【解决方案3】:

    这是一个返回元组列表而不是字典的东西:

    import operator
    
    if __name__ == '__main__':
    
        test_string = 'cnaa'
    
        string_dict = dict()
        for letter in test_string:
            if letter not in string_dict:
                string_dict[letter] = test_string.count(letter)
    
        # Sort dictionary by values, credits go here http://stackoverflow.com/questions/613183/sort-a-dictionary-in-python-by-the-value/613218#613218
        ordered_answer = sorted(string_dict.items(), key=operator.itemgetter(1), reverse=True)
        print ordered_answer
    

    【讨论】:

    • 该死!我只是在使用运算符输入响应! :-) +1 更快获得最佳答案
    • 请注意,可以将 reverse=True 作为 sorted() 的参数。可以说这样会更有效率。我想说这里使用 count() 的效率低于其他答案使用的替代方法,因为这需要对字符串进行多次迭代。
    • +1 这个答案最接近标准库实现 collections.Counter.most_common() 的方式。
    【解决方案4】:

    Python 2.7 直接支持这个用例:

    >>> from collections import Counter
    >>> Counter('abracadabra').most_common()
    [('a', 5), ('r', 2), ('b', 2), ('c', 1), ('d', 1)]
    

    【讨论】:

    • 可爱的柜台,没有它就活不下去。只是为了好奇,当数据扩大时,内存无法容纳整个数据。如何扩大我们的收藏。计数器根据?我想在可以使用 Counter 轻松完成时处理一些日志文件,除非它的大小现在远远超出计算机的内存大小。
    【解决方案5】:

    chills42 lambda 函数获胜,我认为,但作为替代方案,如何生成以计数作为键的字典?

    def count_chars(string):
        distinct = set(string)
        dictionary = {}
        for s in distinct:
            num = len(string.split(s)) - 1
            dictionary[num] = s
        return dictionary
    
    def print_dict_in_reverse_order(d):
        _list = d.keys()
        _list.sort()
        _list.reverse()
        for s in _list:
            print d[s]
    

    【讨论】:

    • 如果 2 个字符的计数相同,您的代码会给出不正确的结果
    • 为什么?在问题或我的解决方案中,未定义两个具有相同计数的字母的打印顺序。
    【解决方案6】:

    EDIT 这会做你想做的事。我正在窃取 chills42 行并添加另一个:

    sortedLetters = sorted(d.iteritems(), key=lambda (k,v): (v,k))
    sortedString = ''.join([c[0] for c in reversed(sortedLetters)])
    

    ------------原始答案------------

    要打印出排序后的字符串,请在 chills42 单行中添加另一行:

    ''.join(map(lambda c: str(c[0]*c[1]), reversed(sortedLetters)))
    

    这会打印出'bbbaac'

    如果你想要单个字母,'bac' 使用这个:

    ''.join([c[0] for c in reversed(sortedLetters)])
    

    【讨论】:

      【解决方案7】:
      from collections import defaultdict
      
      def most_frequent(s):
          d = defaultdict(int)
          for c in s:
              d[c] += 1
      
          return "".join([
              k for k, v in sorted(
              d.iteritems(), reverse=True, key=lambda (k, v): v)
          ])
      

      编辑:

      这是我的一个班轮:

      def most_frequent(s):
          return "".join([
              c for frequency, c in sorted(
                  [(s.count(c), c) for c in set(s)], reverse=True
              )
          ])
      

      【讨论】:

      • 感谢您指出 s.count()!只为那条信息投票!
      • 公平地说,hyperboreean首先提到了count方法。就个人而言,我不喜欢这种方法,因为它会遍历每个字母的字符串。虽然,它有助于制作优雅的单衬:)
      【解决方案8】:

      这是您的 most_frequent 函数的代码:

      >>> a = 'aabbbc'
      >>> {i: a.count(i) for i in set(a)}
      {'a': 2, 'c': 1, 'b': 3}
      

      这种特殊的语法适用于 py3k,但使用以前版本的语法很容易编写类似的东西。在我看来,它比你的更具可读性。

      【讨论】:

      • 这可行,但与 Chill 的版本或 collections.Counter 版本相比速度较慢。
      【解决方案9】:
      def reversedSortedFrequency(string)
         from collections import defaultdict
         d = defaultdict(int)
         for c in string:
           d[c]+=1
         return sorted([(v,k) for k,v in d.items()], key=lambda (k,v): -k)
      

      【讨论】:

      • 为什么不使用 reversed=True 而不是 key 函数来反转 k?
      【解决方案10】:

      这里是修正版(感谢指出错误)

      def frequency(s):
          return ''.join(
              [k for k, v in
              sorted(
                  reduce(
                      lambda d, c: d.update([[c, d.get(c, 0) + 1]]) or d, 
                      list(s), 
                      dict()).items(),
                  lambda a, b: cmp(a[1], b[1]),
                  reverse=True)])
      

      我认为reduce 的使用使得这个解决方案与其他解决方案相比有所不同......

      在行动:

      >>> from frequency import frequency
      >>> frequency('abbbccddddxxxyyyyyz')
      'ydbxcaz'
      

      还包括提取密钥(并计算它们)!!!另一个不错的属性是在同一行上初始化字典:)

      另外:不包含,只有内置。

      reduce 函数有点难以理解,在 lambda 中设置字典值在 python 中也有点麻烦,但是,嗯,它可以工作!

      【讨论】:

      • 如何投票?您按字母排序,而不是频率。我没有足够的声誉来投票反对...
      • 哎呀!对字符串进行排序只是为了对其进行标记。应该使用 list 代替,以免混淆您和我自己,因为输出是随机顺序的,即 keys()。
      • 修复了该功能,将排序添加到包含频率的字典中。这也可能是一个很好的例子,说明为什么单行代码在生产代码中编写起来既有趣又不好!
      猜你喜欢
      • 1970-01-01
      • 2021-03-05
      • 2017-08-30
      • 2022-12-21
      • 2022-12-04
      • 2012-05-20
      • 2021-04-12
      • 2014-06-26
      • 1970-01-01
      相关资源
      最近更新 更多