tags:

views:

79

answers:

3

Ok say I have a string in python:

str="martin added 1 new photo to the <a href=''>martins photos</a> album."

the string contains a lot more css/html in real world use

What is the fastest way to change the 1 ('1 new photo') to say '2 new photos'. of course later the '1' may say '12'. Note, I don't know what the number is, so doing a replace is not acceptable. I also need to change 'photo' to 'photos' but I can just do a .replace(...). Unless there is a neater, easier solution to modify both?

+2  A: 

since you're not parsing html, just use an regular expression

import re

exp = "{0} added ([0-9]*) new photo".format(name)
number = int(re.findall(exp, strng)[0])

This assumes that you will always pass it a string with the number in it. If not, you'll get an IndexError.

I would store the number and the format string though, in addition to the formatted string. when the number changes, remake the format string and replace your stored copy of it. This will be much mo'bettah' then trying to parse a string to get the count.

In response to your question about the html mattering, I don't think so. You are not trying to extract information that the html is encoding so you are not parsing html with regular expressions. This is just a string as far as that concern goes.

aaronasterling
Ah. That would be too easy. We dont have a count of photos. Its in the string. We need to retreive it. we cant do a search for 1. it would need to be more advanced.
spidee
@spidee So the markup has been generated already, and there's no way for you to change the code that does so?
NullUserException
In fact, to be more precise. We need to find the count of photos from the string and then change it. the user name and the photo album name along with the css and html may have numbers - so we cant do a number search. I would imagine the best approach maybe a split as added_ and _new to get the number?
spidee
Yep thats correct we have the markup stored we want to jump in grab the count of photos and adjust it.
spidee
@spidee. Your system is seriously broken.
aaronasterling
We can add a count into the data. We have a template string stored - as that is how the string was made in the first place. If this is that difficult. I guess we will have to store the count. and re-make a new string.
spidee
How would we do this with a regular expression? can you offer any code. The string does have html in it. Does that matter?
spidee
@spidee updated
aaronasterling
Aaron. That looks workable. We dont need to change the user name. Just the count and photo to photos if >0.
spidee
updated my response
spidee
I think storing the count - and the format string is now the best route. I think it was worth the debate. Thanks for all your help.
spidee
+3  A: 

Update

Never mind. From the comments it is evident that the OP's requirement is more complicated than it appears in the question. I don't think it can be solved by my answer.

Original Answer

You can convert the string to a template and store it. Use placeholders for the variables.

template = """%(user)s added %(count)s new %(l_object)s to the 
      <a href='%(url)s'>%(text)s</a> album."""

options = dict(user = "Martin", count = 1, l_object = 'photo', 
      url = url, text = "Martin's album")

print template % options

This expects the object of the sentence to be pluralized externally. If you want this logic (or more complex conditions) in your template(s) you should look at a templating engine such as Jinja or Cheetah.

Manoj Govindan
that would be so much prettier with modern formatting. as it stands, the +1 and -1 cancel eachother out. ;)
aaronasterling
@Aaron: I'll move to Python3 one of these days and then you'll see ;)
Manoj Govindan
Yes but the string is stored as a formated string. Not as a template. The string could be rendered millions of times. But changed rarely. So it is stored in its formated state.
spidee
no, you'll see. when you have to convert all the code with old style formatting ;)
aaronasterling
@Aaron: I guess I'd better start writing a custom 2to3 post-haste :P
Manoj Govindan
+2  A: 

It sounds like this is what you want (although why is another question :^)

import re

def add_photos(s,n):
    def helper(m):
        num = int(m.group(1)) + n
        plural = '' if num == 1 else 's'
        return 'added %d new photo%s' % (num,plural)
    return re.sub(r'added (\d+) new photo(s?)',helper,s)

s = "martin added 0 new photos to the <a href=''>martins photos</a> album."
s = add_photos(s,1)
print s
s = add_photos(s,5)
print s
s = add_photos(s,7)
print s

Output

martin added 1 new photo to the <a href=''>martins photos</a> album.
martin added 6 new photos to the <a href=''>martins photos</a> album.
martin added 13 new photos to the <a href=''>martins photos</a> album.
Mark Tolonen
Thats very clever. Is that a poor solution. Is it better for us to go to the length of storing the photo count, and perhaps the template and doing it as suggested?
spidee
+1. Just finished writing this. Serves me right for not knowing the re lib off the top of my head. @spidee. It's better to store the format string and the formatted string. just replace the formatted string instead of trying to parse it. Either way, you should accept this answer because it answers the question you asked.
aaronasterling
@Aaron. Yes you are very humble. I think this re implementation is wicked. And as you say does what was written on this box. In practice i think we will store the data that is needed and re-make the string as you and others have said. Again thanks to all. I think this was an interesting process, served well by all. Including yourself.
spidee
@spidee/aaron, thanks for the accepted answer. As you say, it answers the question, but in reality storing the data is the way to go.
Mark Tolonen