Python映射、Lambda和string.replace

2024-10-03 09:17:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道如何在不使用lambda/map的情况下解决我的问题(在本练习中,我不能使用regex或其他python库),使用带有string.replace()的for循环……但我确实在尝试使用map/lambda和string.replace的组合是否能达到同样的效果

我的目标是读入一个txt文件,然后用字母“e”替换非标准“e”(如的每个实例)

我现在的主要问题是,我得到了6个列表(例如,我在新文件/新文件列表理解中有6个字符串,并且每个字符串都根据评估的1个iterable更新了原始字符串

例如,newFile[0]=输出.replace('ee')newFile[1]=输出.replace('ee')

所以我想返回格式化字符串的1个副本,所有的.replace()都在上面迭代

我在下面引用的文本文件的链接可以访问https://easyupload.io/s7m0zj

import string

def file2str(filename):
    with open(filename, 'r', encoding="utf8") as fid:
        return fid.read()

def count_letter_e(filename, ignore_accents, ignore_case):
    eSToAvoid = 'éêèÉÊÈ'
    textFile = file2str("Sentence One.txt")
    newFileListComprehension = [textFile.replace(e,'e') for e in eSToAvoid if ignore_accents == 1]
    value = textFile.count('e')
    #newFile = list((map(lambda element: (textFile.replace(element, 'e') if ignore_accents == 1 else textFile.count('e')), eSToAvoid)))
    return 0

numberOfEs = count_letter_e("Sentence One.txt", 1, 1)```


Tags: 文件lambda字符串txtmapforstringcount
2条回答

可以使用str.translate一次替换多个字符str.maketrans帮助您创建所需的映射:

eSToAvoid = 'éêèÉÊÈ'
textFile.translate(str.maketrans(eSToAvoid, 'e' * len(eSToAvoid)))

虽然str.replace只能用另一个子字符串替换一个子字符串,但re.sub可以替换一个模式

In [55]: eSToAvoid = 'éêèÉÊÈ' 
In [58]: import re 

测试用例:

In [61]: re.sub(r'[éêèÉÊÈ]', 'e', 'foobar')                                                                          
Out[61]: 'foobar'
In [62]: re.sub(r'[éêèÉÊÈ]', 'e', eSToAvoid)                                                                         
Out[62]: 'eeeeee'
In [63]: re.sub(r'[éêèÉÊÈ]', 'e', 'testingè,É  foobar  è É')                                                         
Out[63]: 'testinge,e  foobar  e e'

字符串替换方法是:

In [70]: astr = 'testingè,É  foobar  è É' 
    ...: for e in eSToAvoid: 
    ...:     astr = astr.replace(e,'e') 
    ...:                                                                                                             
In [71]: astr                                                                                                        
Out[71]: 'testinge,e  foobar  e e'

替换顺序应用于astr。这不能表示为列表理解(或map)。列表理解最自然地取代了在列表中收集其结果的循环(使用^{

for循环没有问题。它实际上更快:

In [72]: %%timeit 
    ...: astr = 'testingè,É  foobar  è É' 
    ...: for e in eSToAvoid: 
    ...:     astr = astr.replace(e,'e') 
    ...:  
    ...:                                                                                                             
1.37 µs ± 8.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [73]: timeit re.sub(r'[éêèÉÊÈ]', 'e', 'testingè,É  foobar  è É')                                                  
2.79 µs ± 15.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [77]: timeit astr.translate(str.maketrans(eSToAvoid, 'e' * len(eSToAvoid)))                                       
2.56 µs ± 14.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

减少

In [93]: from functools import reduce  
In [96]: reduce(lambda s,e: s.replace(e,'e'),eSToAvoid, 'testingè,É  foobar  è É' )                                  
Out[96]: 'testinge,e  foobar  e e'
In [97]: timeit reduce(lambda s,e: s.replace(e,'e'),eSToAvoid, 'testingè,É  foobar  è É' )                           
2.11 µs ± 32.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

为了好玩,您还可以探索此处介绍的一些想法:

Cleanest way to combine reduce and map in Python

您想要“累积”更改,要做到这一点,您需要某种类型的累加器,即挂在最后一次替换上的累加器itertools有一个accumulate函数,py3.8引入了一个:=walrus操作符

发电机

In [110]: def foo(astr, es): 
     ...:     for e in es: 
     ...:         astr = astr.replace(e,'e') 
     ...:         yield astr 
     ...:                                                                                                            
In [111]: list(foo(astr, eSToAvoid))                                                                                 
Out[111]: 
['testingè,É  foobar  è É',
 'testingè,É  foobar  è É',
 'testinge,É  foobar  e É',
 'testinge,e  foobar  e e',
 'testinge,e  foobar  e e',
 'testinge,e  foobar  e e']

或者[s for s in foo(astr, eSToAvoid)]代替list()。这突出了一个事实,即列表理解返回一个字符串列表,即使字符串累积了更改

相关问题 更多 >