简体   繁体   中英

multiple string replace by position in python

I need to replace a string in a string with an augmented string.

My question is, with every replace the positions of the strings in info and the original string change: How can I update it in a pythonic way?

str = 'If you do not know where you are going, any road will get you there.'

info = {'you': [(3, 3), (25, 3)], 'get you': [(54, 7)], 'know': [(14, 4)]}

# replace 'you' from info with '<b>you</b>' and 'know' with '<i>know</i>'
# results in

str = 'If <b>you</b> do not <i>know</i> where <b>you</b> are going, any road will get you there.'

info = {'<b>you</b>': [(3, 10), (25, 10)], 'get you': [(54, 7)], '<i>know</i>': [(21, 11)]}

my solution so far:

str = 'If you do not know where you are going, any road will get you there.'
info = {'you': [(3, 3), (25, 3)], 'get you': [(54, 7)], 'know': [(14, 4)]}

replacer = [('you', '<b>you</b>'), ('know', '<i>know</i>')]

for s, s2 in replacer:
    print "replacing %s to %s and update position info dict" % (s, s2)

    old_s_pos = info[s]
    diff = len(s2) - len(s)

    new_key_pos = [(old_s_pos[0][0], old_s_pos[0][1] + diff)]

    old_s_pos = old_s_pos[1:]
    if old_s_pos:
        next_old_s_pos_start = old_s_pos[0][0]
    else:
        next_old_s_pos_start = None

    del info[s]

    for key, positions in info.iteritems():

        new_positions = []                    
        for i, (x,y) in enumerate(positions):

            if x < next_old_key_pos_start:
                new_positions.append((x + diff, y))
            else:
                new_positions.append((x, y))

                if next_old_s_pos_start is not None:
                    # update old_s_pos at first pair
                    new_key_pos.append((old_key_pos[0][0], old_s_pos[0][1] + diff))
                    old_s_pos = old_s_pos[1:]
                    if old_s_pos:
                        next_old_s_pos_start = old_s_pos[0][0]

        info[key] = new_positions
    info[s2] = new_key_pos

    print info   

Kind regards, Matthias

This is based on the idea that you should just replace going backwards through the string. First I had to modify your info and replacer structures a little bit:

str = 'If you do not know where you are going, any road will get you there.'
info = {'you': [(3, 3), (25, 3)], 'get you': [(54, 7)], 'know': [(14, 4)]}
replacer = [('you', '<b>you</b>'), ('know', '<i>know</i>')]

info2 = {}
replacer2 = {}

for original, replacement in replacer:
    replacer2[original] = replacement

for k, v in info.items():
    for start, length in v:
        replacement = None
        if k in replacer2:
            replacement = replacer2[k]
        info2[start] = (k, length, replacement)

for position in sorted(info2.iterkeys(), reverse=True):
    original, length, replacement = info2[position]
    if replacement is not None:
        str[:position] + replacement + str[position + length]

print str

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM