Python 用“替换文本文件中元音的函数”_&引用;
我正在尝试创建一个函数,用“\ux”替换文本文件中的所有元音 这是我目前的代码:Python 用“替换文本文件中元音的函数”_&引用;,python,python-2.7,Python,Python 2.7,我正在尝试创建一个函数,用“\ux”替换文本文件中的所有元音 这是我目前的代码: filename = 'test.txt' wordfile= open(filename) one_line = wordfile.readline() for ch in one_line: if ch in "aeiouAEIOU": print one_line.replace(ch,"_") one_line = wordfile.readline() wordfile.clo
filename = 'test.txt'
wordfile= open(filename)
one_line = wordfile.readline()
for ch in one_line:
if ch in "aeiouAEIOU":
print one_line.replace(ch,"_")
one_line = wordfile.readline()
wordfile.close()
我的文本文件上写着“昼夜滴答”
它的输出应该是:
t_ck t_ck _r__nd th_ cl_ck
但是,这是我的输出:
t_ck tock around the clock
tick t_ck ar_und the cl_ck
tick tock _round the clock
tick t_ck ar_und the cl_ck
tick tock aro_nd the clock
tick tock around th_ clock
tick t_ck ar_und the cl_ck
有人能解释一下为什么不是一行吗?把打印行放在for循环之外
for ch in one_line:
# YOUR CODE
print one_line
更新
完整代码:
for ch in one_line:
if ch in "aeiouAEIOU":
one_line = one_line.replace(ch,"_")
print one_line
您没有沿循环引用保存在
一行上所做的更新
必须在每次循环出现时将更新保存在变量中,才能获得最终结果
filename = 'test.txt'
wordfile= open(filename)
one_line = wordfile.readline()
output = one_line
for ch in one_line:
if ch in "aeiouAEIOU":
output = output.replace(ch,"_")
print(output)
语法:
str.replace(old, new[, max])
方法replace()
返回字符串的copy
,在该字符串中,旧的已替换为新的,可以选择将替换次数限制为最大
所以当你这样做的时候:
for ch in one_line:
if ch in "aeiouAEIOU":
print one_line.replace(ch,"_")
您没有替换一行
要获得预期结果,您需要更新一行,如下所示:
for ch in one_line:
if ch in "aeiouAEIOU":
one_line = one_line.replace(ch,"_")
print(one_line)
然而,“Zohaib Ijaz”提出的解决方案要好得多:
data = re.sub("[aAeEiIoOuU]+", "_" ,data)
您正在迭代输入中的每个字符,如果有字符匹配,则打印整行。这种情况发生了好几次。此外,在该打印中,仅替换一个字符的出现。请注意,对字符串应用replace
不会更改该字符串。只有返回值进行了替换
您可以使用较少的一个循环来完成此操作,但将replace
回调的结果分配给字符串变量:
for ch in "aeiouAEIOU":
one_line = one_line.replace(ch,"_")
print (one_line)
考虑在一次操作中使用re.sub
:
import re
print (re.sub('[aeiouAEIOU]', '_', one_line))
以下是如何替换元音
data = wordfile.read()
data = re.sub("[aAeEiIoOuU]+", "_" ,data)
现在将更新的文本写回文件
例子
输出:'H_ll_)w_rld R_ply(s_m_t_xt)和s_m_R_ply(m_R_t_xt)和th_t_
代码的问题是它只读取文件的一行
尝试此代码,它将读取文件中的所有行,每行它将扫描所有字母,并将元音替换为。
filename = 'test.txt'
with open(filename) as file:
for line in file:
print "".join(map(lambda x: '_' if x in "aeiouAEIOU" else x, line))
首先,让我们重新格式化您的代码以匹配现代python实践:
filename = 'test.txt'
with open(filename, 'r') as wordfile:
one_line = wordfile.readline()
for ch in one_line:
if ch in "aeiouAEIOU":
print(one_line.replace(ch,"_"))
您的代码中有什么错误:
- 对于已知的每个voyel,您迭代该行的每个字符,然后打印一个由voyel替换的字符,因此您正在打印替换的
len(一行)
- 返回一个新字符串,并完成您要求的替换,参见文档:
返回字符串的副本,其中所有出现的子字符串old都替换为new
因此,每次您在voyel上迭代时,您仍然在修改原始字符串
如何改进?
replace
适用于整个字符串,因此您不需要对行中的字符进行迭代,但您可以迭代所有voyels,并通过用replace中的新字符串替换字符串来替换字符串中的字符:
filename = 'test.txt'
with open(filename, 'r') as wordfile:
one_line = wordfile.readline()
for c in 'aoeui':
one_line = one_line.replace(c,"_")
one_line = one_line.replace(c.upper(),'_')
print(one_line)
但这里的问题是,您仍然必须迭代'aoeui'
,并为每个voyel替换两次一行
我们可以做得更好
我相信这就是你写上述算法时的意图:
new_line=''
for c in one_line:
if c.lower() in 'aoeui':
new_line += c
else:
new_line += '_'
这更有效,但太冗长了。因此,是的,我们可以做得更好,我们可以使用:
也可以使用列表理解来编写:
one_line = ''.join(['_' if c.lower() in 'aoeui' else c for c in one_line])
print(one_line)
在这里,我们只需构建一个新字符串,以便对于c
的每个字符,如果c
是一个voyel(无论字符大小写是什么),则将其替换为\uu
,或者保持原样。然后,'.join()
方法就是从列表中生成一个字符串
最后还有一个更好的方法来解决这个问题,那就是使用正则表达式:
import re
re.sub('[aoeui]', '_', one_line, flags=re.IGNORECASE)
print(one_line)
这是怎么回事?它实际上是在构建所谓的有限状态自动机,它将与上面的映射等价,并在输出字符串中放置一个'
或原始字符
注意:IGNORECASE
标志用于检查aoeui
和aoeui
,而无需重复自己的操作。您可以打印循环的每个迭代,而不是像一行=一行那样重新分配。替换(ch,”
,然后在循环外的末端打印。顺便说一句,python的方法可能是使用str.maketrans()
您没有将任何答案标记为选定答案。这将只打印原始行。我在for循环中添加了一条注释,说明您的代码,因为他的逻辑是正确的。只是他的打印语句放错了地方。如果你看用户的最后一行输出(勾选t_u u r_u_u u u u u u u u u u u u u u u u u k
),你会发现不是“只是他的打印语句放错了地方
”。不,@prakarverma,把它移出循环是行不通的。试试看。字符串是不可变的。好吧,我错了。我认为这很明显,他会做到的。马上编辑我的答案。谢谢各位。有时假设会让你丧命;)cf我的回答是,您的正则表达式缺少re.DOTALL
标志(默认情况下,s///g
参数@zmore.sub
将替换所有出现的情况(这可能受count
参数的影响)“re.DOTALL
标志完全是关于其他内容的,对于此正则表达式没有用处,因为它没有点。请参阅我的答案下的.cf注释,mea culpa.cf我的答案,您的正则表达式缺少re.DOTALL
标志。”(在添加此答案之前,我已经测试了s///g
参数@zmo。我在我的答案下添加了一个示例输入和输出。cf注释mea culpa.cf我的答案,您的正则表达式缺少re.DOTALL
标志(使用s///g
参数@zmo,正则表达式不需要re.DOTALL
,并且它会替换所有出现的情况。请参阅我的答案下我对您的评论。cf我的答案下的评论,我的错。您对DOTALL
标志的解释是错误的。更糟糕的是,您使用了comm
one_line = ''.join(['_' if c.lower() in 'aoeui' else c for c in one_line])
print(one_line)
import re
re.sub('[aoeui]', '_', one_line, flags=re.IGNORECASE)
print(one_line)