Установите условие внутри лямбда-функции в зависимости от того, является ли значение, захваченное с помощью регулярного выражения, None или ""

import re

input_text = 'desde el 2022_-_12_-_10 corrimos juntas hasta el 11° nivel de aquella montaña hasta el 2022_-_12_-_13' #example 1
#input_text = 'desde el 2022_-_11_-_10 18:30 pm hasta el 2022_-_12_-_01 21:00 hs' #example 2

#text in the middle associated with the date range...
some_text = r"(?:(?!\.\s*)[^;])*" #but cannot contain ";", ".\s*"

identificate_hours = r"(?:a\s*las|a\s*la|)\s*(?:\(|)\s*(\d{1,2}):(\d{1,2})\s*(?:(am)|(pm)|)\s*(?:\)|)" #no acepta que no se le indicase el 'am' o el 'pm'

date_format = r"(?:\(|)\s*(\d*)_-_(\d{2})_-_(\d{2})\s*(?:\)|)"

some_text_limiters = [r",\s*hasta", r"hasta", r"al", r"a "]


for some_text_limiter in some_text_limiters:

    identification_re_0 = r"(?:(?<=\s)|^)(?:desde\s*el|desde|del|de\s*el|de\s*la|de |)\s*(?:día|dia|fecha|)\s*(?:del|de\s*el|de |)\s*" + date_format + r"\s*(?:" + identificate_hours + r"|)\s*(?:\)|)\s*(" + some_text + r")\s*" + some_text_limiter + r"\s*(?:el|la|)\s*(?:fecha|d[íi]a|)\s*(?:del|de\s*el|de|)\s*" + date_format + r"\s*(?:" + identificate_hours + r"|)\s*(?:\)|)"

    input_text = re.sub(identification_re_0,
                        lambda m: if (r"{m[1]}" == None or r"{m[1]}" == " " or r"{m[1]}" == "") : (f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))").replace(" )", ")").replace("( ", "(") else : (f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))({m[8]})").replace(" )", ")").replace("( ", "("),
                        input_text, re.IGNORECASE)

print(repr(input_text))

Я получаю SyntaxError: invalid syntax эту лямбду lambda m: if (r"{m[8]}" == None or r"{m[8]}" == " " or r"{m[8]}" == "") : (f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))").replace(" )", ")").replace("( ", "(") else : (f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))({m[8]})").replace(" )", ")").replace("( ", "(")

Как мне оценить условия внутри лямбда-функции, размещенной внутри параметра функции re.sub()?

Lambda m: if (r"{m[8]}" == None or r"{m[8]}" == " " or r"{m[8]}" == "") : else:

Вся оценка условного выражения зависит от "{m[8]}", и результаты должны быть такими:

#for example 1, where {m[8]} is not None
'(2022_-_12_-_(10(00:00 am)_--_2022_-_12_-_(13(00:00 am)))(corrimos juntas hasta el 11° nivel de aquella montaña)'

#for example 2, where {m[8]} is None, and remove the last ()
'(2022_-_11_-_(10(18:30 pm)_--_2022_-_12_-_(01(21:00 am)))()hs' #wrong output
'(2022_-_11_-_(10(18:30 pm)_--_2022_-_12_-_(01(21:00 am)))hs' #correct output

Изменить вопрос с ошибкой:

def sub_rule(m):
    res_true = f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))"

    # ternary expression is general, not limited to lambdas
    return (
        res_true.replace(" )", ")").replace("( ", "(")
        if (r"{m[8]}" == None or r"{m[8]}" == " " or r"{m[8]}" == "") 
        else 
        (res_true + f"({m[8]})").replace(" )", ")").replace("( ", "(")
        )


some_text_limiters = [r",\s*hasta", r"hasta", r"al", r"a "]

for some_text_limiter in some_text_limiters:

    identification_re_0 = r"(?:(?<=\s)|^)(?:desde\s*el|desde|del|de\s*el|de\s*la|de |)\s*(?:día|dia|fecha|)\s*(?:del|de\s*el|de |)\s*" + date_format + r"\s*(?:" + identificate_hours + r"|)\s*(?:\)|)\s*(" + some_text + r")\s*" + some_text_limiter + r"\s*(?:el|la|)\s*(?:fecha|d[íi]a|)\s*(?:del|de\s*el|de|)\s*" + date_format + r"\s*(?:" + identificate_hours + r"|)\s*(?:\)|)"

    input_text = re.sub(identification_re_0,
                        sub_rule,
                        input_text, re.IGNORECASE)

И неправильный вывод:

'(2022_-_12_-_(10(00:00 am)_--_2022_-_12_-_(13(00:00 am)))()'

И правильный вывод в примере 2:

'(2022_-_12_-_(10(00:00 am)_--_2022_-_12_-_(13(00:00 am)))'

Обновлено еще раз: мне удалось выполнить условное, хотя и не в той же лямбде

def remove_or_not_parentheses_from_middle_text(m):

    print(repr(m[8]))

    if ( str(m[8]) == None or str(m[8]) == " " or str(m[8]) == ""): res_true = (f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))").replace(" )", ")").replace("( ", "(")
    else: res_true = (f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))({m[8]})").replace(" )", ")").replace("( ", "(")

    return res_true

Вы не можете включать оператор if внутрь лямбда-выражения. Если вы не можете удобно разместить лямбда-выражение в одной строке, замените его функцией, определенной оператором def. Один не более эффективен, чем другой; оба создают значения типа function. Разница заключается в том, «загромождаете» ли вы текущую область действия именем, которое не будете использовать более одного раза.

chepner 10.01.2023 17:46

Кроме того, ваше лямбда-выражение должно оцениваться на каждой итерации цикла, но оно не меняется от одной к другой. Определите его один раз с помощью оператора def перед циклом и повторно используйте одну и ту же функцию для каждого вызова re.sub.

chepner 10.01.2023 17:47

@chepner Вы правы, в любом случае предпочтительнее, чтобы это было в одной строке с лямбда-функцией, однако вы правы и может быть удобнее сделать это в отдельной функции

Matt095 10.01.2023 18:56

Я не могу воспроизвести ваш вывод, см.

cards 10.01.2023 19:45

@cards, потому что вы используете пример 1, то есть input_text = 'from 2022_-_12_-_10 we ran together up to the 11th level of that mountain until 2022_-_12_-_13' #example 1, а ошибка связана с примером 2 input_text = 'desde el 2022_-_11_-_10 18:30 pm hasta el 2022_-_12_-_01 21:00 hs' #example 2

Matt095 10.01.2023 19:49
Потяните за рычаг выброса энергососущих проектов
Потяните за рычаг выброса энергососущих проектов
На этой неделе моя команда отменила проект, над которым я работал. Неделя усилий пошла насмарку.
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
Учебник по веб-скрапингу
Учебник по веб-скрапингу
Привет, ребята... В этот раз мы поговорим о веб-скрейпинге. Целью этого обсуждения будет узнать и понять, что такое веб-скрейпинг, а также узнать, как...
0
5
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Используйте тернарное выражение условного предложения, (do) if (condition) else (do other).

f = lambda x: True if x > 0 else False
print(f(10))
# True

Возможна также вложенность

g = lambda x: '-' if x < 0 else '+' if x < 10 else '+ but more than 10'
print(g(5))
# +

Подсказка: разбивайте длинные выражения на несколько строк с помощью ( и ), например, так

lambda m: (
        f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))")
       .replace(" )", ")")
       .replace("( ", "(")
   )
   if (r"{m[1]}" == None or r"{m[1]}" == " " or r"{m[1]}" == "") 
   else (
       f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))({m[8]})")
      .replace(" )", ")")
      .replace("( ", "(")
   )

В этом случае функция lambda не лучший выбор:

  • как упоминал Чепнер, функция зависит только от объекта match, а не от переменных итераций
  • чистая инициализация переменной не может быть выполнена с помощью lambda и здесь может быть полезно, потому что результат каждой условной ветви почти одинаков
# outside the loop

def sub_rule(m):
    res_true = f"({m[1]}_-_{m[2]}_-_({m[3]}({m[4] or '00'}:{m[5] or '00'} {m[6] or m[7] or 'am'})_--_{m[9]}_-_{m[10]}_-_({m[11]}({m[12] or '00'}:{m[13] or '00'} {m[14] or m[15] or 'am'})))"

    # ternary expression is general, not limited to lambdas
    return (
        res_true.replace(" )", ")").replace("( ", "(")
        if (r"{m[1]}" == None or r"{m[1]}" == " " or r"{m[1]}" == "") 
        else 
        (res_true + f"({m[8]})").replace(" )", ")").replace("( ", "(")
        )

Я пробовал это, но это дает мне неверный результат '(2022_-_12_-_(10(00:00 am)_--_2022_-_12_-_(13(00:00 am)))({m[8]})' ; Там я отредактировал вопрос с новым кодом

Matt095 10.01.2023 18:52

Ах извините! Я забыл префикс формата строки. Так должно быть res_true + f"({m[8]})")

cards 10.01.2023 18:56

Я изменяю if (r"{m[1]}" == None or r"{m[1]}" == " " or r"{m[1]}" == "") на if (r"{m[8]}" == None or r"{m[8]}" == " " or r"{m[8]}" == "") , но все равно выдает неверный результат в примере 2, '(2022_-_11_-_(10(18:30 pm)_--_2022_-_12_-_(01(21:00 am)))()hs'

Matt095 10.01.2023 19:03

Я не изменил логику программы, а просто перефразировал условное выражение в лямбде. Я не могу воспроизвести ваш вывод. Вместо этого я получаю (2022_-_12_-_(10(00:00 am)_--_2022_-_12_-_(13(00:00 am)))(corrimos juntas hasta el 11° nivel de aquella montaña)

cards 10.01.2023 19:12

С примером 2 у меня была проблема, когда m[8] равно None

Matt095 10.01.2023 19:16

Извините, но это другой вопрос. Я не знаю, что делает ваш код. Подсказка: сравнение с None нужно делать как с var is None, а не с ==. В коде есть (возможно!) путаница со сравнением с None. Что такое r"{m[1]}" == None? r"{m[1]}" возвращает строку, а не None

cards 10.01.2023 19:23

Код работает хорошо, единственная проблема в том, что он не входит в условие if в примере 2. В примере 1 работает хорошо, потому что это входит в условие else

Matt095 10.01.2023 19:30

1. какое условие должно вызвать пример 2? 2. попробуйте удалить условие r"{m[1]}" == None и проверьте, изменился ли вывод

cards 10.01.2023 19:35

Я редактирую вопрос с кодом и правильным и неправильным ответом в примере 2

Matt095 10.01.2023 19:39

Я предпринял еще несколько попыток, но понять всю логику программы для меня слишком сложно... работа с таким количеством групп и рекурсивная подстановка занимают слишком много времени, а также уводят меня далеко от исходного вопроса. Я предлагаю вам настроить минимальный рабочий пример, он также может быть вам полезен для выявления проблемы.

cards 10.01.2023 20:34

В любом случае, большое спасибо за помощь, в любом случае логика регулярных выражений работает нормально, что не работает, так это условный журнал внутри лямбда-функции. Теперь добавьте редактирование, где я указал, как должна быть функция модификатора, хотя она дает мне SybtaxError в условных выражениях.

Matt095 10.01.2023 20:45

Основываясь на вашем ответе, я построил функцию с условными выражениями, хотя это не лямбда-функция, но она работает достаточно хорошо. Действительно большое спасибо за ответ.

Matt095 11.01.2023 00:32

Другие вопросы по теме

Как преобразовать код для записи данных в xlsx вместо csv, используя python без панд?
Обновление ключей словаря в одну строку
Правильный способ обработки гигантских строк с многопроцессорной обработкой
Создает новый словарь, состоящий из другого ключа словаря и двух переменных
Установите регулярное выражение с множественным выбором, чтобы попытки сопоставления всегда выполнялись слева направо, независимо от того, пытается ли другое предыдущее регулярное выражение захватить больше символов?
Ошибка из селена: AttributeError: объект «Сервис» не имеет атрибута «процесс»
Создать новый столбец типа списка на основе операции деления существующих столбцов в pandas
Ошибка установки Anaconda на macOS Ventura
Как использовать события (Chrome-Developer-Tools), используя Selenium с Python в качестве потока?
Распечатать данные sql, сгруппированные в одну строку, без повторения строки