【问题标题】:Rewrite char frequency of string as comprehension将字符串的字符频率重写为理解
【发布时间】:2019-04-05 00:29:43
【问题描述】:

以下程序代码 sn-p 计算文本字符串的字符频率并写入字典中。字典以字符为键,以频率为值。

text = "asampletextstring"
char_count = {}
for char in text:
    if char_count.get(char):
        char_count[char] += 1
    else:
        char_count[char] = 1

我的问题是,是否可以将上面的 sn-p 重写为comprehension

【问题讨论】:

  • 为什么要理解?
  • 不理解,但更短:char_count = Counter(text)
  • @mad_ 想把sn-p写的更简洁一些,也想学习pythonic的做事方式。 @dvnguyen 是的,我知道 Counter,但我认为可能有一种无需导入任何东西的方法......
  • dictslists也是pythonic。理解可能会减少一些代码行,但可能不会每次都那么高效

标签: python dictionary-comprehension


【解决方案1】:

重写 - 不是真的,我没有看到任何简单的方法。我到达的最好的需要额外的字典。

d = {}
{ c: d.get(c, 0)  for c in text if d.update( {c: d.get(c,0) + 1} ) or True}

可以在 Python 3.8 中获得单行,但通过 (ab) 使用赋值表达式

【讨论】:

    【解决方案2】:

    每次我使用字典推导、通过将输入转换为集合的字典推导和传统的 for 循环进行一些分析时,我都好奇地研究各种方法的性能并证明推导并不好。理解为什么在这里很昂贵是有道理的,因为 .count() 每次都迭代整个 text 以计算单个 char 的频率

    from timeit import timeit
    
    print('Approach 1 without set compehrension: {}'.format(timeit ('{ch: text.count(ch) for ch in text}',setup='text = "asampletextstring"',number=1000000)))
    print('Approach 2 with set compehrension: {}'.format(timeit ('{ch: text.count(ch) for ch in set(text)}',setup='text = "asampletextstring"',number=1000000)))
    print('Approach 3 simple loops :{}'.format(timeit('for c in text:char_count[c] = char_count.get(c, 0) + 1',setup='text = "asampletextstring";char_count={};',number=1000000)))
    print('Approach 4 Counter :{}'.format(timeit('Counter(text)',setup='text = "asampletextstring";from collections import Counter;',number=1000000)))
    

    输出:

    Approach 1 without set compehrension: 4.43441867505
    Approach 2 with set compehrension: 3.98101747791
    Approach 3 simple loops :2.60219633984
    Approach 4 Counter :7.54261124884
    

    【讨论】:

    • 计数器对于长字符串和字母非常有效,根据stackoverflow.com/questions/41594940/…中的测量值
    • with setup='text = "asampletextstring" * 1000;from collections import Counter;',number=100))),时间为
    • 没有设置的方法 1,理解:16.287531096022576 有设置和理解的方法 2:0.02602811809629202 方法 3 简单循环:0.19724294892512262 方法 4 计数器:0.0549338900018
    • 我不明白你的意思。我的意思是比较给定的文本而不是大小序列。时间值可能因操作系统和处理能力而异,但相对时间仍然很重要。如果我遗漏了一些明显的东西,请告诉我
    • 我很想研究各种方法的性能并证明朴素循环并不总是像指定的标准工具或模块那样好。
    【解决方案3】:

    可以在此处使用set() 以避免遇到该字符 2 次或更多次。

    text = "asampletextstring"
    dict1 = {ch: text.count(ch) for ch in set(text)}
    
    print(dict1)
    {'s': 2, 'r': 1, 'i': 1, 'n': 1, 'a': 2, 'e': 2, 'p': 1, 't': 3, 'x': 1, 'l': 1, 'g': 1, 'm': 1}
    

    【讨论】:

    【解决方案4】:

    有可能,但效率低下

    text = "asampletextstring"
    
    char_count = { char : text.count(char) for char in text }
    
    print(char_count)
    

    输出

    {'s': 2, 'x': 1, 'p': 1, 'm': 1, 'e': 2, 'r': 1, 'n': 1, 'g': 1, 'a': 2, 'i': 1, 'l': 1, 't': 3}
    

    您可以编写更短的代码:

    char_count = {}
    for char in text:
        char_count[char] = char_count.get(char, 0) + 1
    

    【讨论】:

    • 计数器对于主题起始者给出的短字符串效率低下,但对于长文本(比如 10 000)非常有用,请参阅我在测量主题中的讨论
    • 按照上面的建议提供了一次迭代 set(text)
    猜你喜欢
    • 2011-05-28
    • 1970-01-01
    • 2018-09-25
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    相关资源
    最近更新 更多