5

My regex is something like below

    text = 'id 5 result pass
            id 4 result fail
            id 3 result fail
            id 2 result fail
            id 1 result pass'

    for i in re.finditer('id (.+?) result (.+)', text): 
         id = i.group(1)
         result = i.group(2)
         print 'id' 
         print 'result' 

The output is OK. But how do I reverse it to get the results in the other order where id will start from 1 with the pass or fail result

4 Answers 4

7

A good way is (which will be faster than using a lambda in the sorted):

sorted(re.finditer(...,text),key=attrgetter('group'),reverse=True):

Or you could turn the iterator into a list and reverse it:

for i in reversed(list(re.finditer('id (.+?) result (.+)', text))): 
Sign up to request clarification or add additional context in comments.

2 Comments

This pattern is particularly appropriate when using finditer to discover changes to the text. Hmm. I'd better elaborate in a separate answer
Your first example don't work (TypeError thrown using Python 3, incorrect results using Python 2). To make it workable, one should use methodcaller instead or attrgetter (since group is a match object method rather than property): for i in sorted(re.finditer('id (.+?) result (.+)', text), key=methodcaller('group', 1)): ...
4

Assign the finditer call to a list and reverse it.

matches = list(re.finditer(...))
matches.reverse()

for i in matches:
   # etc.

Comments

1

You could sort by the value of the id. This will also work ok if the records are originally in a random order.

for i in sorted(re.finditer('id (.+?) result (.+)', text), key=lambda m:int(m.group(1))):

In the example given, the sort has O(n) complexity, since timsort detects the input as a single "run"

Comments

1

When using finditer to change text we want to discover the changes first, and then make the changes in reverse order. Something like this:

# Pass 1: Find all replacements without changing the text.
replacements = []
for mo in pattern.finditer(text):
    # This may be arbitrarily complicated...
    << compute old, new text based on mo >>
    replacements.append((old, new),)

# Pass 2: Safely make all replacements by making them in reverse order.
for old, new in reversed(replacements):
    text = text.replace(old, new)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.