0

I have the following list:

str_list = [1,3,"foo bar",10]

What I want to do is to simply iterate through it print the results. Stop if the iteration meets "foo bar".

I tried the following code:

In [6]: for x in str_list:
   ...:     print x
   ...:     if x is "foo bar":
   ...:         break
   ...:     

It continues to print string with and after "foo bar". It didn't to to what I expect it to do, i.e. simply printing this:

1
3

What's the right way to do it?

neversaint
  • 60,904
  • 137
  • 310
  • 477

5 Answers5

2

You just need to print after checking. And if it is the string you are looking for in the check, just break. Like this:

>>> str_list = [1,3,"foo bar",10]
>>> for item in str_list:
...     if item == 'foo bar':
...         break
...     print item
...
1
3

Also, it is important to note the difference between using is and using ==. As mentioned in this answer, is checks if both the variables point to the same object. == checks if objects referred to by the variables are equal. So you should be using == here.

Community
  • 1
  • 1
shaktimaan
  • 11,962
  • 2
  • 29
  • 33
2

itertools.takewhile was written specifically for this purpose, though I am not a particular fan as it add an unnecessary function call through lambda and often its difficult to debug

>>> from itertools import takewhile
>>> for elem in takewhile(lambda e: e != "foo bar", str_list):
    print elem


1
3
Abhijit
  • 62,056
  • 18
  • 131
  • 204
1

You need to print the items of the list after you check for the desired string.

for x in str_list:
    if x == "foo bar":
        break
    print(x)

However there are more pythonic ways of doing this:

 try:
     foo_idx = str_list.index('foo bar')
 except ValueError:
     print(str_list)
 else:
     print(str_list[:foo_idx])

And if you wanted this to return something formated like you were showing in your questions:

 try:
     foo_idx = str_list.index('foo bar')
 except ValueError:
     print('\n'.join(map(str, str_list)))
 else:
     print('\n'.join(map(str, str_list[:foo_idx])))
MrAlias
  • 1,316
  • 15
  • 26
  • I would enjoy the feedback from all the down voters. – MrAlias Jul 18 '14 at 02:51
  • I am not the downvoter, but your second implementation is overtly complex. Remember `Simple is better than complex` – Abhijit Jul 18 '14 at 03:02
  • @Abhijit Thanks for the feedback. I tried to highlight python's duck typing and return a string like the one in the question. – MrAlias Jul 18 '14 at 03:05
  • Yes, but this was probably not a very good example to show duck typing. In fact, I do not see any merits out here to do so. Remember "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck" , but how can you apply the duck test here? – Abhijit Jul 18 '14 at 03:09
  • @Abhijit, good point, I miss typed! What I was trying to showcase was the "it's easier to ask for forgiveness than permission" mentality that, for the most part, is encouraged over the "look before you leap" style. – MrAlias Jul 18 '14 at 03:12
0

The easiest way of doing this is by splitting using your desired value ...

Let us say that you have the list

s = [1,3,"foo bar",10]

Then,

s[:s.index('foo bar')]

is a list till the location of 'foo bar'. Of course, if 'foo bar' isn't in the list, then it will throw an error. Then you can change the above line to

s[:s.index('foo bar')] if 'foo bar' in s else s
ssm
  • 5,277
  • 1
  • 24
  • 42
0
str_list = [1,3,"foo bar",10]

for x in str_list:
     if x is "foo bar":
         break
     print x
Abhishek Mittal
  • 356
  • 1
  • 16