0

Suppose I have the list, which I have edited so it's not just called "list" anymore

my_list = ['a b', 'b c d e', 'c', 'd e f g h', 'e f g h i j', 'f g h', 'g h']

I am trying to examine a specific element in the list, and see if one of the elements contains a certain string. I've been using something along the lines of the code below:

for i in range(len(my_list)):
    splitList = my_list[i].split(' ')
    if splitList[3] == "c":
        print "True"
    else:
        print "False"

but what I really want to do is check to see if splitList[3] even exists, and if it does, if it == "c" or simply print the 3rd "thing" in the element. (I'm being generic in my question, but my actual data is looking for a specific 3 character string) I'm certain regular expressions would solve all my problems but I've been looking for the perfect regex solution for days and am overwhelmed and without a solution. My data is very predictable and and I just need to check if the second word in an element of a list is there or not.

Is there a simple pythonic way to check to see if the a list even HAS something at a specific index, and if it does to go on from there?


If you want to suggest a regex solution, the 24th element in my list is always "G# Abc" '#' can be 1-12 inclusive and then the 25th element may also be
" G# Abc" with '#' as 1-12 if the 25th element is not in the format " G# Abc", then the element and any other elements is not relevant. If it is in the format " G# Abc", I need to add the number to a new list.

emmagras
  • 1,378
  • 2
  • 18
  • 25
  • 1
    Just so you know, you can iterate over a list directly.. no need to get its length, build a range, then access each via index. – jdi Jun 01 '12 at 17:08
  • I'm not quite clear what you are asking as far as the checking of the 3rd element and all that, but the loop itself can be simplified: for i in l: splitList = i.split() – Paolo Bergantino Jun 01 '12 at 17:09
  • @wagras don't use `list` as a variable name as it is already a builtin function you will hide – Zeugma Jun 01 '12 at 17:12
  • 1
    To clarify @jdi, you (almost) never do `for i in range(len(my_list))`. Either do `for elt in my_list` or -- if you need the index -- `for i, elt in enumerate(my_list)`. – Katriel Jun 01 '12 at 17:12
  • Thanks for the comments, everyone. and I shan't be using "list" as my list name any more. – emmagras Jun 01 '12 at 17:20

3 Answers3

7

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

relevant_elements = set()
for values in my_list:
    try:
        elt = values.split()[3]
    except IndexError:
        continue
    else:
        if is_correct_format(elt):
            relevant_elements.add(elt)
Katriel
  • 120,462
  • 19
  • 136
  • 170
  • Hah. I hate to have to comment again, but dicts dont have an `add()` method ;-) – jdi Jun 01 '12 at 17:12
  • @jdi oops, too much maths. Thanks. – Katriel Jun 01 '12 at 17:13
  • The reason I didn't "accept" this answer was simply because I don't understand it well enough to feel comfortable implementing it. The thg453's answer is at my level so I used it, although this seems more elegant. – emmagras Jun 04 '12 at 21:51
4

Given an arbitrary string 'x y z', split into a list ['x', 'y', 'z'] with 'x y z'.split(), the simple pythonic way to test whether an index exists is len. Modifying your code above slightly:

# don't use `list` as a variable name; it masks the built-in `list` constructor
str_list = ['a b', 'b c d e', 'c', 'd e f g h', 'e f g h i j', 'f g h', 'g h']
for s in str_list:
    split_list = s.split(' ')
    if len(split_list) > 3 and split_list[3] == 'c':
        print "True"
    else:
        print "False"
georg
  • 211,518
  • 52
  • 313
  • 390
senderle
  • 145,869
  • 36
  • 209
  • 233
  • @katrielalex what does "EAFP" mean? – Kijewski Jun 01 '12 at 17:13
  • 1
    [It's Easier to Ask Forgiveness than Permission](http://docs.python.org/glossary.html#term-eafp): It's one of the Python programming style conventions. It means that instead of checking whether something is OK to do, you do it and catch the exception if it wasn't. – Katriel Jun 01 '12 at 17:15
  • This works perfectly. I've never successfully used and 'if' statement with an 'and.' Not so complicated. Thank you. – emmagras Jun 01 '12 at 17:16
  • 3
    @katrielalex, it's not always easier. Catching an exception is expensive; `try`/`except` should only be used when it's likely that the `try` block will succeed. In other words, `except` is for exceptional cases. If both cases are equally likely, `if` will be much faster. – senderle Jun 01 '12 at 17:22
  • @katrielalex, IYI, I saw a blog post a while ago with some pretty revealing timings, but couldn't find it again. [This answer](http://stackoverflow.com/a/3111386/577088) by Alex Martelli is less thorough, but gets the point across pretty well nonetheless. – senderle Jun 01 '12 at 17:41
4

Use the power of functional programming.

With Python2:

from itertools import imap
for i in (x[3] for x in imap(str.split, input_strings) if len(x) >= 4):
     print i

With Python3:

for i in (x[3] for x in map(str.split, input_strings) if len(x) >= 4):
     print(i)

(Mentioned by @thg435: "you could use from future_builtins import map and from __future__ import print_function to make py2 solution identical to py3.")

Explanation:

  • str.split is a function, that splits the input at (runs of) whitespace characters.
  • map resp. imap applies it to all members of the list. Both function generate a generator.
  • The if len(x) >= 4 tests if a fourth item (located at index 3) exists.
  • The (x[3] for x in ... if ...) generates a generator, that takes the fourth element of the split string list.
Community
  • 1
  • 1
Kijewski
  • 25,517
  • 12
  • 101
  • 143
  • 2
    I'd hate to say this but the code here is just hideous. I absolutely LOVE FP. But there is no way any beginner can look at those two lines and without thinking about it for 10 ~ minutes, decode what it is you are trying to do. – Arnab Datta Jun 01 '12 at 17:15
  • (EDIT: That is, `map` is inefficient in Python 2.x and you should use `imap` instead. It's fine in Python 3.x) – Katriel Jun 01 '12 at 17:19
  • @katrielalex I am here to learn, thanks for mentioning `imap`! – Kijewski Jun 01 '12 at 17:25
  • 1
    The downvote was by me. I removed it now, as it looks a bit better, but I'd still recommend you to do 1 thing and only 1 thing per line. You don't need to save lines of code you know, the rainforest will be saved by saving paper :-) – Arnab Datta Jun 01 '12 at 17:29
  • 1
    Just two more nitpicks: you could use `from future_builtins import map` and `from __future__ import print_function` to make py2 solution identical to py3. And don't call a list `list`. – georg Jun 01 '12 at 17:34
  • @thg435 I woundn't have called it `list` if the wasn't the name OP gave it. I really don't like `from __future__`. It feels like a hack. :-/ – Kijewski Jun 01 '12 at 17:36
  • @thg435 gotta admit that you are right: calling it `list` makes it awful to understand. – Kijewski Jun 01 '12 at 17:42