Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用“替换文本文件中元音的函数”_&引用;_Python_Python 2.7 - Fatal编程技术网

Python 用“替换文本文件中元音的函数”_&引用;

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

我正在尝试创建一个函数,用“\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.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
参数@zmo
re.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)