Как я могу преобразовать `A_B_C_DEF` в `ABC_DEF`?

У меня есть строки этой формы:

A_B_CDEF_GHI
A_B_C_DEF_G_H_I
ABC_D_E_F_GHI
ABCDEFG_H_I
A_B_C

Мне нужно преобразовать их в следующее:

AB_CDEF_GHI
ABC_DEF_GHI
ABC_DEF_GHI
ABCDEFG_HI
ABC

Итак, правила:

  • (._){2,} следует преобразовать в XXX_, если он не находится в конце строки.
  • Если (_.){2,} встречается в конце строки, его следует преобразовать в _XXX.
  • Если (_.){2,}. является строкой весь, все символы подчеркивания должны быть удалены.

Я добрался до (((.)_){2,}), что соответствует первому правилу, но как я могу заменить его найденными символами без подчеркивания?

The python tag is present because that's where the code is, and I know regex dialects depend on the language.

Как приятно читать четкий, лаконичный, недвусмысленный вопрос!

Cary Swoveland 22.03.2022 21:19

'____B_CDEF_GHI' (4 знака подчеркивания в начале) превратиться в 'B_CDEF_GHI'?

Cary Swoveland 22.03.2022 21:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
2
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Точка в вашем примере кода соответствует любому символу, включая подчеркивание. Вместо этого вы можете сделать шаблон немного более конкретным.

Вы можете убрать все двойные совпадения A-Z и захватить одиночные A-Z, за которыми следуют _ и A-Z в группе.

Затем для группы захвата замените _ пустой строкой.

_?[A-Z]{2,}_?|([A-Z](?:_[A-Z](?![A-Z]))+)
  • _?[A-Z]{2,}_? Сопоставьте 2 или более вхождений A-Z, окруженных необязательными символами подчеркивания.
  • | или
  • ( Захватить группа 1
    • [A-Z] Сопоставьте один A-Z
    • (?:_[A-Z](?![A-Z]))+ Повторите 1+ раз _ и AZ, утверждая, а не AZ вправо
  • ) Закрыть группу 1

См. демонстрация регулярных выражений и демонстрация Python

Например:

import re
pattern = r'_?[A-Z]{2,}_?|([A-Z](?:_[A-Z](?![A-Z]))+)'
s = ("A_B_CDEF_GHI\n"
            "A_B_C_DEF_G_H_I\n"
            "ABC_D_E_F_GHI\n"
            "ABCDEFG_H_I\n"
            "A_B_C")

res = re.sub(pattern, lambda x: x.group(1).replace("_", "") if x.group(1) else x.group(), s)
print(res)

Выход

AB_CDEF_GHI
ABC_DEF_GHI
ABC_DEF_GHI
ABCDEFG_HI
ABC

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

_?[^_\s]{2,}_?|([^_\s](?:_[^_\s](?![^_\s]))+)

Большое спасибо. Это сработало отлично. Сэкономил столько времени, пытаясь понять, как это сделать программно.

Chuck 22.03.2022 21:39

Вот решение без регулярных выражений:

def convert(s: str) -> str:
    """ https://stackoverflow.com/q/71578300 """

    def _get_combined_parts() -> Iterator[str]:
        """
        yields the ``_``-separated parts of ``s``
        where subsequent single-character parts have been combined
        """
        combined_part = ""
        for part in s.split("_"):
            if len(part) <= 1:
                combined_part += part
            else:
                if combined_part:
                    yield combined_part
                yield part
                combined_part = ""
        if combined_part:
            yield combined_part

    return "_".join(_get_combined_parts())

Несколько измерений в моей системе показывают, что мое решение в два раза быстрее, чем решение stackoverflow.com/a/71578365/13134095. ?

Manfred 22.03.2022 22:06

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