1

In C, as well as in C++, one can in a for-loop change the index (for example i). This can be useful to, for example, compare a current element and based on that comparison compare the next element:

for(int i = 0; i < end; i++)
  if(array[i] == ':')
    if(array[++i] == ')')
      smileyDetected = true;

Now I know this cannot be done in Python (for various reasons). However, I cannot help wondering if there are short alternatives for Python? I can come up with:

while i < end:
    if array[i] == ':':
        i += 1
        if array[i] == ')':
            smileyDetected = True;

However, this costs me an extra line, which doesn't sound so bad until you do the same multiple times ('less readable' did not mean having a long file). So to have it in one line, I would think of something like array[i += 1], but this is invalid syntax as it seems.

Is there Python equivalent which does the incrementation of the index in the same line as reading out that incremented index?

EDIT:
As most answers mention using in to find a substring, as an alternative for the particular example, let me add another example which wouldn't be solvable in such a way:

j = 0;
for(int i = 0; i < end; i++)
  if(array[i] == ':')
    if(array[++i] == ')')
      anotherArray[j++] = array[++i];

With that I mean it's about the incrementing of the index, not the finding of a particular string.

Community
  • 1
  • 1
Simon Klaver
  • 480
  • 5
  • 24
  • Why don't you iterate the string in *pairs* of characters? – jonrsharpe May 14 '16 at 15:41
  • 1
    The C/C++ will show undefined behavior if the array is no C-string and ':' is the last character. –  May 14 '16 at 15:45
  • If `array` is a string you could just write `smiley_detected = ':)' in array`. – kennytm May 14 '16 at 16:00
  • SImplify like this (non-pythonic way and langauge agnostic) while i < end: if array[i] == ':' and array[i+1]==')': smileyDetected = True i += 1 – manugupt1 May 14 '16 at 16:04
  • @DieterLücking Not if `end` is smaller than the last index of `array` ;) @jonrsharpe I want to find what's after the smiley, not if the smiley is there. – Simon Klaver May 14 '16 at 18:21

3 Answers3

2

Perhaps:

smileyDetected = ':)' in "".join(array)

or per @jonrsharpe:

from itertools import tee

# pairwise() from "Itertools Recipes"

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

for a, b in pairwise(array):
    if a == ':' and b == ')':
         smileyDetected = True
cdlane
  • 40,441
  • 5
  • 32
  • 81
1

If array is a string, the shortest pythonic version would obviously be:

smileyDetected = ':)' in array

A more generic / non-string-specific way of doing this would be using iterators:

smileyDetected = (':', ')') in zip(array, array[1:])
aldanor
  • 3,371
  • 2
  • 26
  • 26
0

In this special case, you could do:

for i, char in enumerate(array[:-1]):
    if char == ":" and array[i+1] == ")":
        smiley_detected = True

However, in the more general case, if you need to skip elements, you could modify the raw iterator:

iterator = iter(array)
for char in iterator:
    if char == ":" and next(iterator) == ")":
        smiley_detected = True

Here you need to take more care about the array bounds; if the last element is :, you will get a StopIteration exception from calling next on the depleted iterator. You would need to catch that.

Jonas Schäfer
  • 20,140
  • 5
  • 55
  • 69
  • The second one is wrong for `array = ['a', ':', ')', 'b']`, because it calls next() twice on the **same** iterator every loop. – Valentin Lorentz May 14 '16 at 16:12
  • @ValentinLorentz No, it only calls next twice when the current element is ``:``, as the ``and`` operator is short-circuiting. For the given search pattern this works, because it cannot start with ``)``, thus it does not matter if ``)`` is skipped. – Jonas Schäfer May 15 '16 at 08:15