Use of pipe operator to search for substring in string

current scenario -
1)

('c' or 'a') in 'ab'

gives,

False

as ('c' or 'a') evaluates to 'c'

  1. the substring check could be obtained, but need to write it using any builtin
any([(i in 'ab') for i in ('c', 'a')])

gives,

True
  1. in a match case statement, one could check for exact match of a string,
x = 'ab'
match x:
  case 'ab' | 'c':
    print(1)

gives 1

but this pipe operator does not work for strings outside of match case statement.

expected scenario -

  1. pipe operator works for strings to check for substring in string, so,
('c' | 'a') in 'ab'

gives,

True

I have often found a need to test substring matching for multiple candidates. I don’t think the proposed syntax is the best solution, but I think there’s something there.


Not related to the proposal, there’s an optimisation to your second example: skipping the list creation

any((i in 'ab') for i in ('c', 'a'))

For large iterables (('c', 'a') in this example), this means both not constructing and storing a large list (of boolean values), but also ending the iteration on the first true value found.

2 Likes

Also it is not clear what do you propose to be the result of this sub-expression in your example:

Should it be a special object with a special treatment of the in operator? Can it be useful for something else?

yes that is a bit confusing, one solution is to make it a new object type, just like there is list_iterator, set_iterator, maybe ('c' | 'a') could return an object of type str_lookup.

I am investigating if it could be useful in some other place apart from the in scenario, but in my opinion, the substring search on its own is a pretty common use case in support of this change.

alongside one another way to achieve this is by using,

import re
if re.search('c|a', 'ab'):
  print(1)

where again the pipe operator is used to search the presence of any of these strings inside of re.search.
I would prefer to achieve the same without using the regex module.

there is one more way to achieve this by using a match-case statement and changing the way __eq__ works for a string,

class MatchString(str):
  def __eq__(self, other):
    return other in self

x = MatchString('abcdef')

match x:
  case 'a' | 'b':
    print(1)

gives, 1 as output