0

I have a working set of code that iterates through a string and searches for 2 relevant substrings. (shoutout to user @bulbus for the help!)

The code returns a list of tuples containing the index positions for the location of the next instance of each substring.

For example, if the strings and substrings looked like this:

sub_A = "StringA"
sub_B = "StringB"

s = "abcdefStringAghijklStringB"

Then the code returns the tuple (6,19) because that is the next index position where the two strings exist.

The relevant part of the code looks like this:

[(m.start(),re.compile(sub_b).search(s,m.start()).start()) for m in re.finditer(sub_A,s)]

However, I want to change the code so that it only returns values to the tuple if the value is even. I.E. in my example above the value "19" should not be a valid return.

As an example, let's say this is my new string:

xxStringAStringBStringB

I want the tuple to return (2,16). Because those are the next "valid" returns.

My code currently returns (2,9) but I want to skip the "StringB" at index 9 since it is an odd number.

Thoughts? And thanks!!

occvtech
  • 453
  • 3
  • 10
  • You use the term "touple" extensively in your post. Do you mean tuple? Or is this something else? – Tom Karzes Sep 29 '17 at 23:19
  • Could you filter your final list to met your criteria? – Jason Sperske Sep 29 '17 at 23:19
  • @Jason Sperske: I don't know if I can filter final list - because sometimes the next `StringA` is even, but the next `StringB` is odd. In that case, I would need to ignore that `StringB` - but still use the `StringA` -- does that make sense? .... @Tom Karzes: typo - thanks. – occvtech Sep 29 '17 at 23:21

1 Answers1

1
>>> s = "abcdefStringAghijklStringB"                                                                
>>> [(m.start(),next((x.start() for x in re.compile(sub_B).finditer(s,m.start()) if x.start()%2==0),None)) for m in re.finditer(sub_A,s)]
[(6, None)]
>>> s='xxStringAStringBStringB'                                                                     
>>> [(m.start(),next((x.start() for x in re.compile(sub_B).finditer(s,m.start()) if x.start()%2==0),None)) for m in re.finditer(sub_A,s)]
[(2, 16)]
  1. We use finditer to find all the sub_B after sub_A, but we need to bailout on first condition(even position) that satisfies
  2. To do that we use next() call to bail out of the iteration. Read here for more.
  3. Now if we do not find a sub_B we want the iteration to return a default value in this case we chose None
kaza
  • 2,317
  • 1
  • 16
  • 25
  • Awesome. next() seams to have done it! Thanks again for all your help - and sorry for the delay on responding. – occvtech Oct 04 '17 at 23:29
  • Spoke a little too soon. banging my head against the wall about how I can get the next() interaction to work on the sub_A value as well. I have it working with sub_B with the following full line: `{(k,frameType[k]):[m.start(),len(frameType[k]) + next((x.start() for x in re.compile(frameType[k]).finditer(s,m.start()) if x.start()%2==0),None)) for m in re.finditer(k,s)] for k in frameType}` ... And have tried adding in a next() call for what I thought was the right location, but I get a return of TypeError: 'int' object is not an iterator.... Any thoughts? – occvtech Oct 05 '17 at 01:01
  • Hey can't seem to understand the issue. Do you want to add the detail in the Q or post a new question? – kaza Oct 05 '17 at 01:08
  • Decided to keep banging my head on the wall on this one, and finally have a solution! ended up breaking it up onto multiple lines so I could visualize things a little better and see where my issue was. Basically had to do with ensuring that my `if m.start() %2 == 0` was above the bulk of the loop... Thanks again so much! – occvtech Oct 10 '17 at 21:35
  • @occvtech hey sorry that I did not follow up after your last question. Glad that it worked out for you. – kaza Oct 10 '17 at 23:49