Высокая сложность кода SonarLint [closed]

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

txt = "A **A** is *italic* **bold** but some are *a* *b* **B**"

def fun(text=None):
if text:
    bold_splits = text.split('**')
    for i, s in enumerate(bold_splits):
        if i % 2:
            print('BOLD:', s )
        else:
            italic_splits = s.split('*')
            for m, n in enumerate(italic_splits):
                if m % 2:
                    print('ITALIC:', n )
                else:
                    if n != '':
                        print('NORMAL:', n )

1 ответ
1

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

Поскольку пока у вас нет четкого описания вашей цели, я делаю следующие предположения из вашего кода:

  • Вы хотите разделить каждую последовательность символов в своей строке на одну из категорий, выделенных жирным шрифтом, курсивом и обычным шрифтом, в зависимости от символов, заключенных в 2, 1 или 0 звездочек.
  • Вы хотите сохранить порядок исходной строки.

Если мы запретим звездочки в обычном тексте, регулярное выражение для этого будет довольно простым. Я рекомендую изучить, что он делает на regex101.

**(?P<bold>.+?)**|*(?P<italic>.+?)*|(?P<normal>[^*]+)

Примечательно, что | совпадения символов в первом найденном совпадении слева направо, что означает, что совпадение всегда будет пытаться найти жирный шрифт, затем курсив, а затем обычный.

В Python мы можем перебирать все совпадения, используя re.finditer. Для каждого match, lastgroup вернет имя захваченной группы, поэтому мы можем использовать его в нашем операторе печати, а также использовать его для получения фактического совпадения, которое нас интересует.

def fun(text=None):
    if text:
        for match in re.finditer(r'**(?P<bold>.+?)**|'  # match bold lazily
                                 r'*(?P<italic>.+?)*|'  # match italics lazily
                                 r'(?P<normal>[^*]+)',  # match normal greedily
                                 text):
            print(f'{match.lastgroup.upper()}: {match.group(match.lastgroup)}')

Следует отметить, что если функция вызывается много раз и производительность вызывает беспокойство, вам следует один раз скомпилировать регулярное выражение, прежде чем использовать его в fun.

Регулярное выражение, используемое в этом примере, очень примитивно, потому что вы не указали свои ограничения или даже то, что функция должна делать. Уточнив свой вопрос и объяснив, как крайние случаи нравятся ** a ** *** и **ab*cd** должен себя вести, можно дать более полный ответ.

  • FWIW для поддержки **ab*cd** вы можете изменить жирный шрифт [^*]+ к .+?. Мы можем сделать то же самое для курсива, но пока ничего не изменится. Нежадные поисковые запросы IMO обычно более полезны.

    — Пейлонрайз


  • @Peilonrayz Я отредактировал сообщение, чтобы включить ваше предложение, так как оно действительно чище, спасибо.

    — Итерниам


  • От документация «RE, разделенные символом» | » пробуются слева направо. Когда один шаблон полностью совпадает, эта ветвь принимается. Это означает, что после совпадения A B не будет тестироваться дальше, даже если это приведет к более длительному общему совпадению. Другими словами, ‘|’ оператор никогда не бывает жадным. «

    — RootTwo

  • @RootTwo Я поправил в посте. Изначально я тестировал соответствие aba|aabaa против aabaa, который соответствует последнему, что привело меня к выводу, что использовалось самое длинное совпадение. Вместо этого, похоже, потому что aabaa встречается раньше в строке.

    — Итерниам

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *