Изменение символов между двумя символами в строке

#python #string

Вопрос:

Я должен написать функцию, которая получает строку и возвращает эту строку с символами между "*" в верхнем регистре , например, учитывая эту строку: “I want *this text* to be uppercase” , она возвращает : “I want THIS TEXT to be uppercase” . Вот код, который я написал:

 l = [] def func(s):  inside = False  for i in s:  if i == "*" and not inside:  inside = True  while inside:  if i == "*":  inside = False  else:  i.upper()  l.append(i)    print(s)    

Когда я запускаю программу, она распечатывает текст без каких-либо изменений.
Что я делаю не так?

Комментарии:

1. Строка, на которую ссылается s , никогда не изменяется в вашем коде

Ответ №1:

Во-первых, эта функция ничего не делает s , поэтому print(s) будет выводить все, что было введено, без изменений.

Во — вторых, while inside цикл должен находиться вне этого if оператора-прямо сейчас доступ к нему возможен только тогда, когда i он помечен звездочкой. Уменьшите отступ всего блока на единицу и измените while inside значение на if inside — таким образом, этот код выполняется для всех значений i , когда inside верно.

Далее, вам нужен способ подать сигнал, когда будет достигнута вторая звездочка, или третья, и так далее. Как насчет того, чтобы вместо присвоения inside значения True if i является звездочкой и inside имеет значение False, вы меняете значение inside при каждом достижении звездочки?

 if i == '*':  inside = not inside  

Это сводит на нет любую необходимость возиться с изменениями inside во второй части вашего кода — это помещает всю определяющую логику «я внутри/я снаружи» в одно место.

Затем вы объявили список l за пределами области действия функции, и, похоже, вы хотите добавить в него отредактированные символы, чтобы в конце концов нужный вам ответ оказался в этом списке. Но вы хотите, чтобы ваш ответ был в строке, а не в списке, и обычно не рекомендуется объявлять список в глобальной области, а затем редактировать его во время вызова функции (если вы вызовете функцию более одного раза, список станет беспорядочным!). Объявите пустую строку l = '' в начале функции, а затем вместо добавления к ней символов вы можете добавить их с помощью = оператора.

Вам также необходимо убедиться, что вы добавляете версию в верхнем регистре l = i.upper() или обычную версию, l = i в зависимости от того , верно это или нет inside . Вы можете поместить весь код после if i == '*' строки в else оператор, чтобы перехватить все случаи, i не отмеченные звездочкой.

Собрав все это вместе, ваша функция может выглядеть примерно так:

 def func(s):  l = '' # the string that will be returned (the result of the function)  inside = False   for i in s:  if i == "*": # flip value of inside whenever you see an asterisk  inside = not inside  else: # otherwise, add i to the result  if inside:  l  = i.upper() # uppercase if between two asterisks  else:  l  = i # unchanged if not   return l # and return the modified string  

Затем, чтобы протестировать функцию:

 my_string = "I want *this text* to be uppercase" my_string_modified = func(my_string)   print(my_string) print(my_string_modified)  

Выход:

 I want *this text* to be uppercase I want THIS TEXT to be uppercase  

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

Ответ №2:

Я думаю, вы пытались сделать это более сложным, чем оно есть на самом деле. Вам нужно найти индекс обеих звездочек. Из этого вы можете получить три фрагмента исходной строки и применить функцию upper() к фрагменту между звездочками. Обратите внимание, что этот код завершится ошибкой, если в строке будет меньше двух звездочек.

 def dotricks(s):  i = s.index('*')  j = s.index('*', i i)  return s[0:i]   s[i 1:j].upper()   s[j 1:]  print(dotricks('I want *this text* to be uppercase'))  

Ответ №3:

Вы не изменяете строку в своем коде. В этом правке ниже я присвоил буквы строки новой переменной. И раньше continue пропускал «*». Кроме того, в конце вашего приложения вы получите список букв, которые вам нужно использовать .join() для объединения.

Попробуйте внести это изменение в свой код, протестированный и работающий:

 l = [] def func(s):  inside = False  temp = ""  for i in s:  if i == "*" and not inside:  inside = True  continue  if inside:  if i == "*":  inside = False  continue  else:  temp = i.upper()  else:  temp = i  l.append(temp)    new_string = "".join(l)  print(new_string)  return new_string  func("I want *this text* to be uppercase")  

Комментарии:

1. Вам не нужно объявлять temp пустую строку в начале функции

Ответ №4:

Здесь есть несколько проблем:

  1. Вы ничего не возвращаете внутри своей функции
  2. Ваш while цикл бессмыслен, так как i он не увеличивается внутри него
  3. Вам необходимо назначить i i.upper()
  4. Вам нужно передать входные данные в список

Исправленный код будет выглядеть следующим образом:

 l = [] def func(s):  inside = False  for i in s:  if i == "*" and not inside:  inside = True  while inside:  if i == "*":  inside = False  else:  i.upper()  if i != "*":  l.append(i)  return l  

Комментарии:

1. Этот код возвращает список, содержащий ограничивающие звездочки. Я не уверен, что это то, что было нужно

2. @BrutusForcus Я отредактировал, чтобы удалить звездочки.

Ответ №5:

Разделив строку на символ * , тогда запись в верхнем регистре будет нечетной, а затем соединится вместе. Предполагается, что их всегда четное число * , поэтому их следует считать своего рода зарезервированным символом.

 s = "I want *this text* to be uppercase and *this* as well"  print(' '.join((j.upper() if i%2!=0 else j for i, j in enumerate(s.split('*')))))  

Выход

 I want THIS TEXT to be uppercase and THIS as well  

Ответ №6:

Я бы использовал мощность re модуля:

 import re  st = "I want *this text* to be uppercase and *this one*"  v = re.findall("*(.*?)*", st)  for s in v:  st = st.replace(f'*{s}*', s.upper())  print(st)  

Выход:

 gt;gt;gt; I want THIS TEXT to be uppercase and THIS ONE  

В любом случае, отредактируйте свой код заново:

 def func(s):  l = []  inside = False  for i in s:  if i == "*":   inside = not inside # switch inside on/off when * is found   if inside:  i = i.upper() # upper the character if inside == True  l.append(i)  return l  

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

 if i == "*" and not inside:  inside = True # inside is set to True when * is found....  while inside:  if i == "*":  inside = False # and immediately set to False again!  

Комментарии:

1. Почему бы не использовать re.sub напрямую?

2. re.sub("*(.*?)*", lambda x: x.group().upper(), st) заменил бы текст в том же вызове.

3. @HampusLarsson, ваша замена шаблона не возвращает то, что хочет пользователь. Эти * все еще там

4. re.sub("*(.*?)*", lambda x: x.group().upper().strip("*"), st) Тогда используй это.