Reputation: 15
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
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
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
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
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
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