Luke
Luke

Reputation: 15

How to check if 2 consecutive values in a string are characters in another string

I am trying to check if 2 consecutive values in a string are characters (minus 5 operators I pre-determined). I tried doing this:

test = "abcdefghijklmnop"

bad = "abfj"

for i in test:
    if i in bad and i+1 in bad:
        print("it works")

with no luck. Is there anyway to get the next index of a string inside of a loop?

Thanks!

Upvotes: 1

Views: 2469

Answers (5)

Aaditya Ura
Aaditya Ura

Reputation: 12669

with range method in one line:

test = "abcdefghijklmnop"

bad = "abfj"


print([("true",test[i:i+2]) for i in range(0,len(test),1) if test[i:i+2] in bad])

With recursive approach:

test = "abcdefghijklmnop"

bad = "abfj"


def recursive_approach(test1):
    print(test1)
    if not test1:
        return 0
    else:
        if test1[:2] in bad:
            print('True', test1[:2])
        return recursive_approach(test1[1:])
print(recursive_approach(test))

Upvotes: 0

jpp
jpp

Reputation: 164683

You can use a generator expression with zip for this.

The benefit of using a generator expression versus list comprehension is you do not have to iterate the entire string.

test = "abcdefghijklmnop"
bad = "abfj"
bad_set = set(bad)

res = ((i in bad_set) and (j in bad_set) for i, j in zip(test, test[1:]))

for k in res:
    if k:
        print(k)
        break

# True

Upvotes: 1

Sohaib Farooqi
Sohaib Farooqi

Reputation: 5666

If you are only trying to check whether two consecutive characters of test match in bad(not interested in which two) you can do

>>> any("".join([i,j]) in bad for i,j in zip(test,test[1:]))
>>> True

If you want which two characters match and which of them don't:

>>> [("".join([i,j]) in bad,"".join([i,j])) for i,j in zip(test,test[1:])]
>>> [(True, 'ab'), (False, 'bc'), (False, 'cd'), (False, 'de'), (False, 'ef'), (False, 'fg'), (False, 'gh'), (False, 'hi'), (False, 'ij'), (False, 'jk'), (False, 'kl'), (False, 'lm'), (False, 'mn'), (False, 'no'), (False, 'op')]

Upvotes: 2

abarnert
abarnert

Reputation: 365747

i isn't the index, it's the actual character. That's why you can just write i in bad instead of test[i] in bad.

If you want the index as well as the character, use enumerate, like this:

for idx, ch in enumerate(test):
    if ch in bad and test[idx+1] in bad:

Or just use the index for both:

for idx in range(len(test)):
    if test[idx] in bad and test[idx+1] in bad:

Also, notice that whichever way you do this, you're going to have a bug when you reach the last character—you're going to try to check the next character, but there is no next character.


If you want to think a bit more abstractly, the pairwise function in th recipes in the itertools docs (or you can pip install either toolz or more-itertools; I think they both have it) will let you loop over adjacent pairs of anything. So:

for current_char, next_char in pairwise(test):
    if current_char in bad and next_char in bad:

Or maybe this is a bit easier to understand, if less flexible:

for current_char, next_char in zip(test, test[1:]):
    if current_char in bad and next_char in bad:

Here's another trick that lets you avoid having to do two separate tests, if you understand the idea of set intersection:

bad = set(bad)

for idx in range(len(test)):
    if bad.intersection(test[idx:idx+2]):

You still need to deal with the "last one" problem—you'll get an incorrect test instead of an exception, but it's still wrong.

You can also combine this with pairwise.

Upvotes: 1

Eliethesaiyan
Eliethesaiyan

Reputation: 2322

the i in that loop is a string,therefor you can't use it as an index change this part of the code to this:

for i in range(0,len(test)):
    while(i+1<len(test)):
         if test[i] in bad and test[i+1] in bad:
            print("it works")

Upvotes: -1

Related Questions