将字符串的字符频率重写为理解
Rewrite char frequency of string as comprehension
以下过程代码片段计算文本字符串的字符频率并写入字典。字典以字符作为键,以频率作为值。
text = "asampletextstring"
char_count = {}
for char in text:
if char_count.get(char):
char_count[char] += 1
else:
char_count[char] = 1
我的问题是,是否可以将上面的代码片段重写为 comprehension
?
有可能,但是效率低下:
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
可以在此处使用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}
很好奇地研究了各种方法的性能,并证明每次我使用字典推导、通过将输入转换为集合和传统的 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
重写 - 不是真的,我没有看到任何简单的方法。我到达的最好的需要额外的字典。
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)使用赋值表达式
以下过程代码片段计算文本字符串的字符频率并写入字典。字典以字符作为键,以频率作为值。
text = "asampletextstring"
char_count = {}
for char in text:
if char_count.get(char):
char_count[char] += 1
else:
char_count[char] = 1
我的问题是,是否可以将上面的代码片段重写为 comprehension
?
有可能,但是效率低下:
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
可以在此处使用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}
很好奇地研究了各种方法的性能,并证明每次我使用字典推导、通过将输入转换为集合和传统的 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
重写 - 不是真的,我没有看到任何简单的方法。我到达的最好的需要额外的字典。
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)使用赋值表达式