Python Карта, лямбда и string.replace - PullRequest
0 голосов
/ 14 марта 2020

Я знаю, как решить мою проблему, не используя lambda / map (и я не могу использовать regex или другие библиотеки python для этого упражнения), используя for-l oop с string.replace () .. ..но я действительно пытаюсь понять, смогу ли я достичь того же результата, используя комбинацию map / lambda и string.replace \

Моя цель здесь - прочитать в текстовом файле, а затем заменить каждый экземпляр нестандартного 'e' (например, éêèÉÊÈ ) с буквой 'e'

Моя главная проблема сейчас заключается в том, что я получаю 6 списков (например, у меня есть 6 строк in newFile / newFileListComprehension , и каждая строка обновила исходную строку, основываясь на 1 итерируемой оценке, которая была оценена

например newFile [0] = вывод .replace ('é') , newFile [1] = вывод .replace ('ê') et c .

Итак, я хотел бы вернуть 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)```

Ответы [ 2 ]

1 голос
/ 15 марта 2020

Вы можете использовать str.translate для замены нескольких символов одновременно. str.maketrans помогает вам создать необходимое отображение:

eSToAvoid = 'éêèÉÊÈ'
textFile.translate(str.maketrans(eSToAvoid, 'e' * len(eSToAvoid)))
0 голосов
/ 15 марта 2020

Хотя 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). Понимание списка наиболее естественно заменяет al oop, который собирает свои результаты в списке (с list.append).

Нет ничего плохого в для l oop. Это на самом деле быстрее:

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)

Для развлечения вы также можете изучить некоторые из представленных здесь идей:

Самый чистый способ комбинировать сокращение и отобразите в Python

Вы хотите «накапливать» изменения, и для этого вам нужен какой-то аккумулятор, что-то, что держится до последней замены. itertools имеет функцию accumulate, а в Py 3.8 введен * оператор моржа :=.

генератор

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(). Это подчеркивает тот факт, что понимание списка возвращает список строк, даже если строки накапливают изменения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...