3

Let L be a list of strings.

Here is the code I use for finding a string texttofind in the list L.

texttofind = 'Bonjour'
for s in L:
    if texttofind in s:
        print 'Found!'
        print s
        break

How would you do a Find next feature ? Do I need to store the index of the previously found string?

Basj
  • 41,386
  • 99
  • 383
  • 673

4 Answers4

4

One approach for huge lists would be to use a generator. Suppose you do not know whether the user will need the next match.

def string_in_list(s, entities):
    """Return elements of entities that contain given string."""
    for e in entities:
        if s in e:
            yield e

huge_list = ['you', 'say', 'hello', 'I', 'say', 'goodbye']  # ...
matches = string_in_list('y', huge_list)  # look for strings with letter 'y'
next(matches)  # first match
next(matches)  # second match

The other answers suggesting list comprehensions are great for short lists when you want all results immediately. The nice thing about this approach is that if you never need the third result no time is wasted finding it. Again, it would really only matter for big lists.

Update: If you want the cycle to restart at the first match, you could do something like this...

def string_in_list(s, entities):
    idx = 0
    while idx < len(entities):
        if s in entities[idx]:
            yield entities[idx]
        idx += 1
        if idx >= len(entities):
            # restart from the beginning
            idx = 0
huge_list = ['you', 'say', 'hello']
m = string_in_list('y', huge_list)
next(m)  # you
next(m)  # say
next(m)  # you, again

See How to make a repeating generator for other ideas.

Another Update

It's been years since I first wrote this. Here's a better approach using itertools.cycle:

from itertools import cycle  # will repeat after end

# look for s in items of huge_list
matches = cycle(i for i in huge_list if s in i)
next(matches)
Community
  • 1
  • 1
ChrisP
  • 5,812
  • 1
  • 33
  • 36
  • 2
    Which can be written more concisely as `matches = (line for line in L if s in line)` – Eric Dec 21 '13 at 20:25
  • Note that [`matches.next()` is deprecated in favor of `next(matches)`](http://stackoverflow.com/q/10414210/102441) – Eric Dec 21 '13 at 20:26
  • @Eric, Thanks for pointing that out! I suppose the function is only useful if there is more complicated processing involved in finding a match. – ChrisP Dec 21 '13 at 20:27
  • I would cry if I saw this in code. Perfect candidate for generator expression. – Paul Draper Dec 21 '13 at 22:48
  • thank you. Is `matches = (line for line in L if s in line)` really the same as the code with `def` ... `yield` ? – Basj Dec 21 '13 at 23:01
  • how can I do so that when `next(matches)` reaches the end, it RE-BEGINS from the beginning ? – Basj Dec 21 '13 at 23:04
  • @Basj, Yes it is the same. Generator expressions were introduced some time ago. As others have pointed out, the `(...)` syntax is preferable here. See edited answer for having it restart at the beginning. – ChrisP Dec 22 '13 at 02:26
3

If you want to find all indexes of strings in L which have s as a substring,

[i for i in range(0, len(L)) if L[i].find(s) >= 0]
James King
  • 6,229
  • 3
  • 25
  • 40
3

Finding all strings in L which have as substring s.

[f for f in L if s in f]
Paul Draper
  • 78,542
  • 46
  • 206
  • 285
-1

This will find next if it exists. You can wrap it in function and return None/Empty string if it doesn't.

L = ['Hello', 'Hola', 'Bonjour', 'Salam']

for l in L:
    if l == texttofind:
        print l
        if L.index(l) >= 0 and L.index(l) < len(L):
            print L[L.index(l)+1]
Umair A.
  • 6,690
  • 20
  • 83
  • 130
  • This does not find next, this "nexts find" - it takes the next _line_ after the line with the match – Eric Dec 21 '13 at 20:23