【问题标题】:Python: Dict for counting unique letters in stringPython:用于计算字符串中唯一字母的字典
【发布时间】:2019-01-30 04:05:34
【问题描述】:

在某种程度上,我正在使用 Python 3 中的 String 库来解决这个 HarvardX 挑战,但我认为我的解决方案不是很好。你能找到更简洁的解决方案吗?

这是我的代码:

#writing the 2 strings

alpha = string.ascii_letters

alpha
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

sent = 'She sells seashells on the seashore the seashells she sells are      seashells for sure'
sent
'She sells seashells on the seashore the seashells she sells are seashells for sure'

#WRITING DICT to lookup count alpha string characters within 'She sells(etc)'

mydict_countalpha = {alpha[0]:sent.count(alpha[0]), alpha[1]:sent.count(alpha[1]), alpha[2]:sent.count(alpha[2]), alpha[3]:sent.count(alpha[3]), alpha[4]:sent.count(alpha[4]), alpha[5]:sent.count(alpha[5])}

#result:
mydict_countalpha
{'a': 5, 'b': 0, 'c': 0, 'd': 0, 'e': 16, 'f': 1}

耶。它计数正确。

虽然有问题

字母字符串的长度为 52 个字符。如果我逐行手动编写这本字典,我想我会犯错误。我怎样才能做得更好?跟迭代有关系吗?

我为什么问

这是基于哈佛X 优秀课程“Using Python for Research”的家庭作业。它已经过评估,但根据 HarvardX 指南咨询 Stack Overflow 以找出答案是可以的。 :-) 如果您有任何想法,我并不是在作弊。

我认为这个挑战有非常广泛的应用&希望你也觉得它很有趣。但是,我是一名初学者,Python 学习曲线陡峭。不过,感谢您的任何建议!

最好的

一个

【问题讨论】:

    标签: python string python-3.x dictionary


    【解决方案1】:

    Pythonic 方法是使用collections.Counter 并通过字典理解为ascii_letters 过滤键。为了效率,您可以先将ascii_letters 转换为set

    from collections import Counter
    from string import ascii_letters
    
    letters_set = set(ascii_letters)
    
    res = {k: v for k, v in Counter(sent).items() if k in letters_set}
    
    print(res)
    
    {'S': 1, 'h': 8, 'e': 16, 's': 17, 'l': 10, 'a': 5,
     'o': 3, 'n': 1, 't': 2, 'r': 4, 'f': 1, 'u': 1}
    

    此解决方案具有 O(m + n) 复杂度,而您当前的解决方案具有 O(m * n)。您可以理解str.countlist.count 一样具有O(n) 复杂度,即字典理解中的每次迭代都需要完整解析字符串。

    【讨论】:

      【解决方案2】:

      简单地查看sent 中的每个字母并每次增加该字母的计数似乎要容易得多。

      my_dict = {}
      
      for lett in sent:
          if lett in my_dict:
              my_dict[lett] += 1
          else:
              # first entry
              my_dict[lett] = 1
      

      或者更简单地说,使用dict.setdefault

      for lett in sent:
          my_dict.setdefault(lett, 0) += 1
      

      但是请注意,stdlib 模块 collections 有一个名为 Counter 的对象,它正是这样做的。

      from collections import Counter
      
      my_dict = Counter(sent)
      

      您可以在使用filter 计数之前进一步过滤掉不需要的字母

      alpha = set(string.ascii_letters)
      
      filtered = filter(lambda ch: ch in alpha, sent)
      
      my_dict = Counter(filtered)
      

      【讨论】:

      • 这也会计算那些不在alpha 字符串中的字符,您需要以某种方式过滤掉这些字符...
      • @JoeIddon 是规范的一部分吗?我认为这是 OP 的一个意外限制(但我承认我没有遵循规范的链接)
      • 哦,这两种方法都可以:)我相信 OP 无论如何都会理解这两种方法
      【解决方案3】:

      你可以使用字典理解

      mydict_countalpha = {alpha[x]:sent.count(alpha[x]) for x in range(len(alpha))}
      

      但是没有必要继续查找索引。直接循环alpha

      mydict_countalpha = {ch:sent.count(ch) for ch in alpha}
      

      不过,我通常会使用 collections.Counter

      from collections import Counter
      mydict_countalpha = {k: v for k, v in Counter(sent).items() if k in alpha}
      

      编辑:为循环版本添加

      mydict_countalpha = {}
      for ch in alpha:
          mydict_countalpha[ch] = sent.count(ch)
      

      【讨论】:

      • 酷!使用字典理解确实会得出正确的答案,但是我没有得到分数。 HarvardX 正在寻找我使用 For 循环。更类似于亚当所做的事情......我会尝试在正确的方框中打勾。
      • 他们没有说在问题中使用 For 循环。有点烦人,那个。
      • @avwinter,我添加了一个 for 循环版本。这种方法的主要问题是sent.count 一遍又一遍地扫描整个字符串(alpha 中的每个字符一次)。对于初学者来说,它比使用defaultdictsetdefault 更具可读性
      【解决方案4】:

      使用字典理解:

      mydict_countalpha = {c:sent.count(c) for c in alpha}
      

      但是使用Counter 对象会更有效,因为当前的解决方案是O(n^2),而Counter 对象的创建复杂度是O(n),然后我们可以过滤掉那些不在@ 中的对象987654326@字符串。

      from collections import Counter
      mydict_countalpha = {k:v for k,v in Counter(sent).items() if k in alpha}
      

      【讨论】:

        【解决方案5】:

        在 Edx 讨论论坛上有很多来自其他 HarvardX 学生的 cmets,他们尝试了不同的方法(包括 for 循环或理解)来编写正确答案,但仍然无法获得分数。这里也一样!

        以下是初学者应根据本课程使用的方法。我这里稍微调整了一下,这样浏览这个的同学还是要自己写代码才能通过...

        sentenceA = 'I could not collect points on this homework and that is sad'
        alphabet_string = string.ascii_letters
        count_lett_dict = {}
        for letters in sentenceA:
            if letters in alphabet_string:
                if letters in count_lett_dict:
                    count_lett_dict[letters] += 1
                else:
                    count_lett_dict[letters] = 1
        count_lett_dict
        

        【讨论】:

          猜你喜欢
          • 2016-07-22
          • 2014-07-08
          • 2014-07-17
          • 1970-01-01
          • 1970-01-01
          • 2012-01-11
          • 2023-03-03
          • 2013-08-10
          • 1970-01-01
          相关资源
          最近更新 更多