Check if the string contains list items

How to check if string 'str1' contains elements in list 'lis'?

str1 = "45892190" lis = [89,90] 
+5
source share
7 answers

If the match is not resolved, this problem becomes much more complicated than it seems at first glance. As far as I can tell, no other answer is correct (see Test Examples at the end).

Recursion is necessary because if a substring appears more than once, using one input instead of another can interfere with other substrings.

This answer uses two functions. The first finds each occurrence of a substring in a string and returns an iterator of strings where the substring has been replaced by a character that should not appear in any substring.

The second function recursively checks if there is a way to find all the numbers in a string:

 def find_each_and_replace_by(string, substring, separator='x'): """ list(find_each_and_replace_by('8989', '89', 'x')) # ['x89', '89x'] list(find_each_and_replace_by('9999', '99', 'x')) # ['x99', '9x9', '99x'] list(find_each_and_replace_by('9999', '89', 'x')) # [] """ index = 0 while True: index = string.find(substring, index) if index == -1: return yield string[:index] + separator + string[index + len(substring):] index += 1 def contains_all_without_overlap(string, numbers): """ contains_all_without_overlap("45892190", [89, 90]) # True contains_all_without_overlap("45892190", [89, 90, 4521]) # False """ if len(numbers) == 0: return True substrings = [str(number) for number in numbers] substring = substrings.pop() return any(contains_all_without_overlap(shorter_string, substrings) for shorter_string in find_each_and_replace_by(string, substring, 'x')) 

Here are some examples:

 tests = [ ("45892190", [89, 90], True), ("8990189290", [89, 90, 8990], True), ("123451234", [1234, 2345], True), ("123451234", [2345, 1234], True), ("123451234", [1234, 2346], False), ("123451234", [2346, 1234], False), ("45892190", [89, 90, 4521], False), ("890", [89, 90], False), ("8989", [89, 90], False), ("8989", [12, 34], False) ] for string, numbers, should in tests: result = contains_all_without_overlap(string, numbers) if result == should: print("Correct answer for %-12r and %-14r (%s)" % (string, numbers, result)) else: print("ERROR : %r and %r should return %r, not %r" % (string, numbers, should, result)) 

And the corresponding conclusion:

 Correct answer for '45892190' and [89, 90] (True) Correct answer for '8990189290' and [89, 90, 8990] (True) Correct answer for '123451234' and [1234, 2345] (True) Correct answer for '123451234' and [2345, 1234] (True) Correct answer for '123451234' and [1234, 2346] (False) Correct answer for '123451234' and [2346, 1234] (False) Correct answer for '45892190' and [89, 90, 4521] (False) Correct answer for '890' and [89, 90] (False) Correct answer for '8989' and [89, 90] (False) Correct answer for '8989' and [12, 34] (False) 
+2
source
 str1 = "45892190" lis = [89,90] for i in lis: if str(i) in str1: print("The value " + str(i) + " is in the list") 

OUTPUT:

The value 89 is in the list.

The value 90 is in the list.

If you want to check if all values ​​are in lis in str1, the code is cricket_007

 all(str(l) in str1 for l in lis) out: True 

is what you are looking for

+2
source

If you want matching matches, I would do it like this:

  • make a copy of the original string (how do we modify it)
  • go through each element of the list, and if we find an element in our line, replace it with x
  • at the same time, if we find a number in our line, we increase the counter
  • at the end, if the variable is equal to the length of the list, it means that all its elements are
 str1 = "45890190" lis1 = [89, 90] copy, i = str1, 0 for el in lis1: if str(el) in copy: copy = copy.replace(str(el), 'x') i = i + 1 if i == len(lis1): print(True) 

Moreover, we do not need a counter if we add an additional condition that returns False when the item is not found in the string. That is, we get the following final decision:

 def all_matches(_list, _string): str_copy = _string for el in _list: if str(el) not in str_copy: return False str_copy = str_copy.replace(str(el), 'x') return True 

What you can check by writing:

 str1 = "4589190" lis1 = [89, 90] print(all_matches(lis1, str1)) > True 

This may not be the best solution for what you are looking for, but I believe that it serves the purpose.

+1
source

You can use all() function

 In [1]: str1 = "45892190" ...: lis = [89,90] ...: all(str(l) in str1 for l in lis) ...: Out[1]: True 
0
source
 def contains(s, elems): for elem in elems: index = s.find(elem) if index == -1: return False s = s[:index] + s[index + len(elem) + 1:] return True 

Using:

 >>> str1 = "45892190" >>> lis = [89,90] >>> contains(str1, (str(x) for x in lis)) True >>> contains("890", (str(x) for x in lis)) False 
0
source

You can use regex to search.

 import re str1 = "45892190" lis = [89,90] for i in lis: x = re.search(str(i), str1) print(x) 
0
source

This can be implemented correctly using regular expressions. Generate all unique input permutations, for each permutation, associate the terms with ". *", Then connect all permutations with "|". For example, [89, 90, 8990] turns into 89. * 8990. * 90 | 89. * 90. * 8990 | 8990. * 89. * 90 | 8990. * 90. * 89 | 90. * 89. * 8990 | 90. * 8990. * 89, where I added a space after each "|" for clarity. "

Next is the Eric Duminil test suite.

 import itertools import re def create_numbers_regex(numbers): # Convert each into a string, and double-check that it an integer numbers = ["%d" % number for number in numbers] # Convert to unique regular expression terms regex_terms = set(".*".join(permutation) for permutation in itertools.permutations(numbers)) # Create the regular expression. (Sorted so the order is invariant.) regex = "|".join(sorted(regex_terms)) return regex def contains_all_without_overlap(string, numbers): regex = create_numbers_regex(numbers) pat = re.compile(regex) m = pat.search(string) if m is None: return False return True 

However, and this is large, however, the size of the regular expression in the worst case grows as the factor number of the number of numbers. Even with 8 unique numbers, these are 40,320 regular expressions. Python takes a few seconds to compile this regular expression.

The only time this solution can be useful is if you have multiple numbers and you want to find many lines. In this case, you can also look at re2, which I believe can handle this regular expression without returning.

0
source

Source: https://habr.com/ru/post/1268959/


All Articles