检查特定字符是否在字符串中
Check if specific characters are in a string
我需要查找并计算可以在一个字符串中找到多少个字符。我把字符分为chars1[a:m]和chars2[n:z],有两个计数器。
输出应该是0/14,但实际上是0/1。我认为它只检查是否包含一个且只有一个项目,然后退出循环。是这样吗?
这是代码。
string_1 = "aaabbbbhaijjjm"
def error_printer(s):
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = 0
counter2 = 0
if ((c in s) for c in chars1):
counter1 += 1
elif ((c in s) for c in chars2):
counter2 += 1
print(str(counter2) + "/" + str(counter1))
error_printer(string_1)
chars1
/chars2
中出现在 s
中的字符数
这是有道理的,因为您 以 if
条件 递增。由于 if
是 而不是 在循环中,您可以将其递增一次。
现在我们可以展开生成器进入for
循环。这将解决问题的一部分,并且 生成 0/6
:
<b>for c in chars1:
if c in s:
counter1 += 1</b>
<b>for c in chars2:
if c in s:</b>
counter2 += 1
尽管如此,这仍然不会非常有效:它需要 O(n) 最坏情况来检查字符是否在字符串中。您可以先用字符串中的字符构造一个 set
,然后执行查找(通常是 O(1) 平均情况:
def error_printer(s):
<b>sset = set(s)</b>
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = 0
counter2 = 0
for c in chars1:
if c in <b>sset</b>:
counter1 += 1
for c in chars2:
if c in <b>sset</b>:
counter2 += 1
print(str(counter2) + "/" + str(counter1))
现在效率提高了,但还是不够优雅:代码量大,而且还得看代码才能知道是干什么的。我们可以使用 sum(..)
构造来计算满足特定约束的元素数量,例如:
def error_printer(s):
sset = set(s)
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
<b>counter1 = sum(c in sset for c in chars1)
counter2 = sum(c in sset for c in chars2)</b>
print(str(counter2) + "/" + str(counter1))
这会产生 0/6
,因为 [A-M]
范围内有六个字符出现在 s
中,而 [N-Z]
范围内有 0 个字符出现在 s
.
s
中出现在 char1
/char2
中的字符数
然而,根据问题的正文,您想 计算 s
中出现在两个不同范围 .[=42= 中的字符数]
另一个相关问题是计算 char1
/char2
中出现的字符数。在那种情况下,我们只需 交换循环 :
def error_printer(s):
chars1 = <b>set(</b>"abcdefghijklm"<b>)</b>
chars2 = <b>set(</b>"nopqrstuvwxyz"<b>)</b>
counter1 = sum(c in <b>chars1</b> for c in <b>s</b>)
counter2 = sum(c in <b>chars2</b> for c in <b>s</b>)
print(str(counter2) + "/" + str(counter1))
这会产生 0/14
,因为 s
中有 14 个字符出现在 [A-M]
范围内(如果 'a'
在 s
中出现两次,则我们计算了两次),并且 s
中的 none 个字符出现在 [N-Z]
范围内。
使用范围检查
由于我们正在使用 范围,我们可以使用比较而不是元素检查,并通过两次比较检查使其 运行,例如:
def error_printer(s):
counter1 = sum(<b>'a' <= c <= 'm'</b> for c in s)
counter2 = sum(<b>'n' <= c <= 'z'</b> for c in s)
print(str(counter2) + "/" + str(counter1))
尝试使用 if 条件递增,对 s 进行一次循环。
for c in s:
if c in char1:
counter1 += 1
if c in char2:
counter2 += 1
一个 for 循环遍历 s
两个计数器:
string_1 = "aaabbbbhaijjjm"
def error_printer(s):
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = 0
counter2 = 0
for c in s:
if c in chars1:
counter1 += 1
if c in chars2:
counter2 += 1
print(str(counter2) + "/" + str(counter1))
error_printer(string_1)
for 循环的替代方法:
string_1 = "aaabbbbhaijjjm"
def error_printer(s):
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = sum(s.count(c) for c in chars1)
counter2 = sum(s.count(c) for c in chars2)
print(str(counter2) + "/" + str(counter1))
error_printer(string_1)
你数一下"a"
、"b"
、"c"
...在字符串输入中显示了多少次,然后你总结一下。
它仍然效率低下,但利用了 string.count
和 sum
函数,使其更容易阅读和理解正在发生的事情。
您可以将 collections.Counter
与 sum
结合使用:
from collections import Counter
def error_printer(s):
cnts = Counter(s)
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
print(sum(cnts[c] for c in chars2), '/', sum(cnts[c] for c in chars1))
>>> error_printer("aaabbbbhaijjjm")
0 / 14
正如已经建议的那样,for 循环是可行的方法。您使用生成器表达式作为 if 语句的布尔值,它只会 运行 一次。第一个表达式被计算 True
,但这不会使它 运行 包含的代码不止一次。因为第一个 if
做了 运行,然而,elif
甚至从来没有计算过它的条件。这就是为什么你想要 for 循环,但你不应该循环 char1 和 char2,你想循环 s:
for c in s:
if c in char1:
counter1 += 1
if c in char2:
counter2 += 1
print(str(counter2) + "/" + str(counter1))
这为我们指出了一些更巧妙的方法,首先是使用 c in charX
作为迭代器:
for c in s:
counter1 += c in char1
counter2 += c in char2
现在有点不太清楚了,但我们可以通过添加第二个 for 循环使其更加清晰:
char = [‘abcdefghijklm’,’nopqrstuvwxyz’]
counter = [0,0]
for c in s:
for i in [0,1]:
counter[i] += c in char[i]
这可能有点过头了,但我希望它能帮助您了解如何在 python 中重新排列这些内容!
(根据以下评论进行编辑)
我需要查找并计算可以在一个字符串中找到多少个字符。我把字符分为chars1[a:m]和chars2[n:z],有两个计数器。
输出应该是0/14,但实际上是0/1。我认为它只检查是否包含一个且只有一个项目,然后退出循环。是这样吗?
这是代码。
string_1 = "aaabbbbhaijjjm"
def error_printer(s):
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = 0
counter2 = 0
if ((c in s) for c in chars1):
counter1 += 1
elif ((c in s) for c in chars2):
counter2 += 1
print(str(counter2) + "/" + str(counter1))
error_printer(string_1)
chars1
/chars2
中出现在 s
中的字符数
这是有道理的,因为您 以 if
条件 递增。由于 if
是 而不是 在循环中,您可以将其递增一次。
现在我们可以展开生成器进入for
循环。这将解决问题的一部分,并且 生成 0/6
:
<b>for c in chars1:
if c in s:
counter1 += 1</b>
<b>for c in chars2:
if c in s:</b>
counter2 += 1
尽管如此,这仍然不会非常有效:它需要 O(n) 最坏情况来检查字符是否在字符串中。您可以先用字符串中的字符构造一个 set
,然后执行查找(通常是 O(1) 平均情况:
def error_printer(s):
<b>sset = set(s)</b>
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = 0
counter2 = 0
for c in chars1:
if c in <b>sset</b>:
counter1 += 1
for c in chars2:
if c in <b>sset</b>:
counter2 += 1
print(str(counter2) + "/" + str(counter1))
现在效率提高了,但还是不够优雅:代码量大,而且还得看代码才能知道是干什么的。我们可以使用 sum(..)
构造来计算满足特定约束的元素数量,例如:
def error_printer(s):
sset = set(s)
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
<b>counter1 = sum(c in sset for c in chars1)
counter2 = sum(c in sset for c in chars2)</b>
print(str(counter2) + "/" + str(counter1))
这会产生 0/6
,因为 [A-M]
范围内有六个字符出现在 s
中,而 [N-Z]
范围内有 0 个字符出现在 s
.
s
中出现在 char1
/char2
中的字符数
然而,根据问题的正文,您想 计算 s
中出现在两个不同范围 .[=42= 中的字符数]
另一个相关问题是计算 char1
/char2
中出现的字符数。在那种情况下,我们只需 交换循环 :
def error_printer(s):
chars1 = <b>set(</b>"abcdefghijklm"<b>)</b>
chars2 = <b>set(</b>"nopqrstuvwxyz"<b>)</b>
counter1 = sum(c in <b>chars1</b> for c in <b>s</b>)
counter2 = sum(c in <b>chars2</b> for c in <b>s</b>)
print(str(counter2) + "/" + str(counter1))
这会产生 0/14
,因为 s
中有 14 个字符出现在 [A-M]
范围内(如果 'a'
在 s
中出现两次,则我们计算了两次),并且 s
中的 none 个字符出现在 [N-Z]
范围内。
使用范围检查
由于我们正在使用 范围,我们可以使用比较而不是元素检查,并通过两次比较检查使其 运行,例如:
def error_printer(s):
counter1 = sum(<b>'a' <= c <= 'm'</b> for c in s)
counter2 = sum(<b>'n' <= c <= 'z'</b> for c in s)
print(str(counter2) + "/" + str(counter1))
尝试使用 if 条件递增,对 s 进行一次循环。
for c in s:
if c in char1:
counter1 += 1
if c in char2:
counter2 += 1
一个 for 循环遍历 s
两个计数器:
string_1 = "aaabbbbhaijjjm"
def error_printer(s):
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = 0
counter2 = 0
for c in s:
if c in chars1:
counter1 += 1
if c in chars2:
counter2 += 1
print(str(counter2) + "/" + str(counter1))
error_printer(string_1)
for 循环的替代方法:
string_1 = "aaabbbbhaijjjm"
def error_printer(s):
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
counter1 = sum(s.count(c) for c in chars1)
counter2 = sum(s.count(c) for c in chars2)
print(str(counter2) + "/" + str(counter1))
error_printer(string_1)
你数一下"a"
、"b"
、"c"
...在字符串输入中显示了多少次,然后你总结一下。
它仍然效率低下,但利用了 string.count
和 sum
函数,使其更容易阅读和理解正在发生的事情。
您可以将 collections.Counter
与 sum
结合使用:
from collections import Counter
def error_printer(s):
cnts = Counter(s)
chars1 = "abcdefghijklm"
chars2 = "nopqrstuvwxyz"
print(sum(cnts[c] for c in chars2), '/', sum(cnts[c] for c in chars1))
>>> error_printer("aaabbbbhaijjjm")
0 / 14
正如已经建议的那样,for 循环是可行的方法。您使用生成器表达式作为 if 语句的布尔值,它只会 运行 一次。第一个表达式被计算 True
,但这不会使它 运行 包含的代码不止一次。因为第一个 if
做了 运行,然而,elif
甚至从来没有计算过它的条件。这就是为什么你想要 for 循环,但你不应该循环 char1 和 char2,你想循环 s:
for c in s:
if c in char1:
counter1 += 1
if c in char2:
counter2 += 1
print(str(counter2) + "/" + str(counter1))
这为我们指出了一些更巧妙的方法,首先是使用 c in charX
作为迭代器:
for c in s:
counter1 += c in char1
counter2 += c in char2
现在有点不太清楚了,但我们可以通过添加第二个 for 循环使其更加清晰:
char = [‘abcdefghijklm’,’nopqrstuvwxyz’]
counter = [0,0]
for c in s:
for i in [0,1]:
counter[i] += c in char[i]
这可能有点过头了,但我希望它能帮助您了解如何在 python 中重新排列这些内容!
(根据以下评论进行编辑)