2

I have a list, where each element of the list is the title of a chapter. Each title is formatted in the following way: '[Series name] [chapter number] : [chapter title]' So, an excerpt of my list would be

chapter_title:['One Piece 1 : Romance Dawn', 'One Piece 2 : They Call Him Strawhat Luffy', 'One Piece 3 : Pirate Hunter Zoro Enters']

I want to remove the space between the chapter number and the colon. My working code was:

no_space_regex = re.compile(r'\s:')
for i in chapter_title:
    no_space_regex.sub(':',i)

However, it didn't make the substitution. Moreover, I know the compile works, because if I use re.findall it finds all the whitespaces followed by a colon.

I kinda solved it, using:

no_space_regex = re.compile(r'\s:')
def_chapter=[] #list of chapter titles with no space before :
for i in chapter_title:
    i = no_space_regex.sub(':',i)
    def_chapter.append(i)

but I was wondering why re.sub did not substitute it in place, like it is supposed to.

ulibrau
  • 79
  • 1
  • 5
  • 4
    *"like it is supposed to"* What makes you think that it's supposed to do that? Strings are immutable; it's literally *impossible* for it to do the substitution in-place. – Aran-Fey May 29 '18 at 09:44
  • 1
    The Pythonic way for making a new list by transforming all elements of a list would be to use a list comprehension: `def_chapter = [no_space_regex.sub(':', title) for title in chapter_title]` – mkrieger1 May 29 '18 at 09:46
  • Related/duplicates: [Why doesn't calling a Python string method do anything unless you assign its output?](//stackoverflow.com/q/9189172) and [Re.sub not working for me](//stackoverflow.com/q/8033375). And something about improving that loop: [Call int() function on every list element?](//stackoverflow.com/q/3371269) – Aran-Fey May 29 '18 at 16:40

1 Answers1

3

re.sub can't mutate strings because strings are immutable. All it can do is return a new string.

Your options are a) to build a new list as you did or b) assign to a full slice of your old list if for some reason you really need to keep the identity of chapter_title.

>>> import re
>>> 
>>> chapter_title = ['One Piece 1 : Romance Dawn', 'One Piece 2 : They Call Him Strawhat Luffy', 'One Piece 3 : Pirate Hunter Zoro Enters']
>>> no_space_regex = re.compile(r'\s:')
>>> 
>>> id(chapter_title)
139706643715336
>>> chapter_title[:] = (no_space_regex.sub(':', s) for s in chapter_title)
>>> chapter_title
['One Piece 1: Romance Dawn', 'One Piece 2: They Call Him Strawhat Luffy', 'One Piece 3: Pirate Hunter Zoro Enters']
>>> id(chapter_title)
139706643715336

Note that the second approach still builds new strings while mutating chapter_title in addition. In almost all cases I can think of your original approach will work just fine and the oneliner to reassign chapter_title would look like this:

chapter_title = [no_space_regex.sub(':', s) for s in chapter_title]

edit: changed assignment to full slice to generator expression on the right hand side for memory efficiency

timgeb
  • 76,762
  • 20
  • 123
  • 145
  • Did you really have to reopen the question without even asking for my opinion first? – Aran-Fey May 29 '18 at 14:34
  • 1
    @Aran-Fey I already had typed up much of my answer and was about to post it when the goldhammer hit. Since it addresses OP's specific problem in more detail than the generic dupe target, I made the decision that reopening the question in order to post it would be reasonable. I haven't experienced you as a person who would take reversals of his close vote personal as of yet, so I didn't deem a prolonged discussion necessary. – timgeb May 29 '18 at 16:19
  • I generally don't mind reopening dupes, but it does rub me the wrong way if it's done without any form of communication. In the case that my dupe was straight up incorrect, I *definitely* want to know about it; and even if it's just less-than-ideal, I'd still prefer to be informed of the question being reopened - if only because I may want to link the related question in the comments. But in this particular case, I have to say I really don't see the need for an answer. If it's about rewriting the loop to a list comprehension, well, we have lots of answers about that already. Why add another? – Aran-Fey May 29 '18 at 16:34