【问题标题】:Find count of characters within the string in Python在Python中查找字符串中的字符数
【发布时间】:2017-04-18 11:13:43
【问题描述】:

我正在尝试创建一个单词字典和它在字符串中重复的次数。假设字符串如下所示

str1 = "aabbaba"

我想创建一个这样的字典

word_count = {'a':4,'b':3}

我正在尝试使用字典理解来执行此操作。 我做了

dic = {x:dic[x]+1 if x in dic.keys() else x:1 for x in str}

这最终给出了一个错误提示

  File "<stdin>", line 1
    dic = {x:dic[x]+1 if x in dic.keys() else x:1 for x in str}
                                               ^
SyntaxError: invalid syntax

谁能告诉我语法有什么问题?另外,如何使用字典理解创建这样的字典?

【问题讨论】:

  • 你看过Counter吗?
  • 删除第二个 x: 第一个 x: 是两者的键,if 子句被解析为值的一部分
  • @dawg 我知道柜台。我不想使用计数器。如果可能的话,我想使用字典理解来做到这一点。
  • dict/list/set 理解很酷,但是这并不意味着它们是所有问题的最佳解决方案,这是其中一种情况
  • 也请看this answer

标签: python string dictionary counter dictionary-comprehension


【解决方案1】:

正如其他人所说,最好使用计数器来完成。

你也可以这样做:

>>> {e:str1.count(e) for e in set(str1)}
{'a': 4, 'b': 3}

但是对于每个唯一字符遍历字符串 1+n 次(一次创建集合,每个唯一字母一次以计算它出现的次数。即,这具有二次运行时复杂度。)。如果长字符串中有很多唯一字符,结果会很糟糕...... Counter 只遍历字符串一次。

如果你不想要比使用.count更高效的导入版本,你可以使用.setdefault做一个计数器:

>>> count={}
>>> for c in str1:
...    count[c]=count.setdefault(c, 0)+1
... 
>>> count
{'a': 4, 'b': 3}

无论多长或多少个唯一字符,它只会遍历字符串一次。


如果您愿意,也可以使用defaultdict

>>> from collections import defaultdict
>>> count=defaultdict(int)
>>> for c in str1:
...    count[c]+=1
... 
>>> count
defaultdict(<type 'int'>, {'a': 4, 'b': 3})
>>> dict(count)
{'a': 4, 'b': 3}

但是如果你要导入集合——使用计数器!

【讨论】:

  • 为什么每次迭代都不是count = collections.defaultdict(int) 而不是setdefault
  • @MichaelKohl 避免进口?否则计数器是更好的选择
【解决方案2】:

理想的方法是使用collections.Counter:

>>> from collections import Counter
>>> str1 = "aabbaba"
>>> Counter(str1)
Counter({'a': 4, 'b': 3})

您无法通过简单的 dict 理解 表达式来实现这一点,因为您需要参考之前的元素计数值。正如Dawg's answer 中提到的,作为一种变通方法,您可以使用list.count(e) 来从dict 理解 表达式中的字符串set 中查找每个元素的计数。但时间复杂度将是n*m,因为它将遍历每个唯一元素的完整字符串(其中 m 是唯一元素),而与计数器一样,它将是 n

【讨论】:

    【解决方案3】:

    这是collections.Counter 的一个很好的案例:

    >>> from collections import Counter
    >>> Counter(str1)
    Counter({'a': 4, 'b': 3})
    

    它是 dict 子类,因此您可以像标准字典一样使用对象:

    >>> c = Counter(str1)
    >>> c['a']
    4
    

    您也可以在不使用 Counter 类的情况下执行此操作。简单而高效的python代码是:

    >>> d = {}
    >>> for x in str1:
    ...     d[x] = d.get(x, 0) + 1
    ... 
    >>> d
    {'a': 4, 'b': 3}
    

    【讨论】:

      【解决方案4】:

      请注意,这不是正确的方法,因为它不会多次计算重复字符(除了从原始字典中丢失其他字符),但这回答了 if-else 的原始问题在理解中是可能的,并演示了如何做到这一点。

      要回答你的问题,是的,但方法是这样的:

      dic = {x: (dic[x] + 1 if x in dic else 1) for x in str1}
      

      条件仅应用于值,而不应用于键:值映射。

      以上内容可以使用dict.get更清楚:

      dic = {x: dic.get(x, 0) + 1 for x in str1}
      

      如果x 不在dic 中,则返回0。

      演示:

      In [78]: s = "abcde"
      
      In [79]: dic = {}
      
      In [80]: dic = {x: (dic[x] + 1 if x in dic else 1) for x in s}
      
      In [81]: dic 
      Out[81]: {'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1}
      
      In [82]: s = "abfg"
      
      In [83]: dic = {x: dic.get(x, 0) + 1 for x in s}
      
      In [84]: dic
      Out[84]: {'a': 2, 'b': 2, 'f': 1, 'g': 1}
      

      【讨论】:

      • 你的意思是dic = {x: dic.get(x, 1) for x in str}?您是否在外面的任何地方定义了dic?因为在 dict 理解中它将没有参考
      • 这将失败并显示NameError: name 'dic' is not defined(一旦将 str 修复为 str1)
      • @MoinuddinQuadri 是的,刚刚注意到它,如果你指出它会更有帮助。现已修复
      • 现在如果你想重新开始,你需要重置 dic
      • @Copperfield 这不是正确的做法,但它回答了 OP 关于 if-else 在理解中的问题。
      猜你喜欢
      • 1970-01-01
      • 2023-04-06
      • 2021-08-13
      • 1970-01-01
      • 2014-07-10
      • 2020-10-13
      • 2014-11-29
      • 2018-08-27
      • 2016-10-02
      相关资源
      最近更新 更多