list comprehension for splitting strings into pairs

Discussion in 'Python' started by Steven Bethard, Oct 12, 2004.

  1. Here's what I'm doing:

    >>> lst = ['1', '1:2', '3', '-1:4']
    >>> splits = []
    >>> for s in lst:

    .... pair = s.split(':')
    .... if len(pair) != 2:
    .... pair.append(None)
    .... splits.append(pair)
    ....
    >>> splits

    [['1', None], ['1', '2'], ['3', None], ['-1', '4']]

    Basically, I want to split each string into two items, substituting
    None when no second item is specified in the string. (As you can see,
    in my strings, the items are delimited by ':').

    It seems like a simple enough operation that I should be able to write
    a list comprehension for it, but I can't figure out how... Any
    suggestions?

    Steve
    --
    You can wordify anything if you just verb it.
    - Bucky Katt, Get Fuzzy
    Steven Bethard, Oct 12, 2004
    #1
    1. Advertising

  2. Steven Bethard

    Russell Blau Guest

    "Steven Bethard" <> wrote in message
    news:...
    > Here's what I'm doing:
    >
    > >>> lst = ['1', '1:2', '3', '-1:4']
    > >>> splits = []
    > >>> for s in lst:

    > ... pair = s.split(':')
    > ... if len(pair) != 2:
    > ... pair.append(None)
    > ... splits.append(pair)
    > ...
    > >>> splits

    > [['1', None], ['1', '2'], ['3', None], ['-1', '4']]
    >
    > Basically, I want to split each string into two items, substituting
    > None when no second item is specified in the string. (As you can see,
    > in my strings, the items are delimited by ':').
    >
    > It seems like a simple enough operation that I should be able to write
    > a list comprehension for it, but I can't figure out how... Any
    > suggestions?


    How's this?

    >>> lst = ['1', '1:2', '3', '-1:4']
    >>> splits = [':' in item and item.split(':', 1) or [item, None] \

    for item in lst]
    >>> splits

    [['1', None], ['1', '2'], ['3', None], ['-1', '4']]

    This approach is cute, but lacks any error-checking, so you can only use it
    if you are fairly sure your "lst" will contain strings in the proper format.

    --
    I don't actually read my hotmail account, but you can replace hotmail with
    excite if you really want to reach me.
    Russell Blau, Oct 12, 2004
    #2
    1. Advertising

  3. Steven Bethard

    Bob Follek Guest

    On Tue, 12 Oct 2004 16:11:45 -0600, Steven Bethard
    <> wrote:

    >Here's what I'm doing:
    >
    >>>> lst = ['1', '1:2', '3', '-1:4']
    >>>> splits = []
    >>>> for s in lst:

    >... pair = s.split(':')
    >... if len(pair) != 2:
    >... pair.append(None)
    >... splits.append(pair)
    >...
    >>>> splits

    >[['1', None], ['1', '2'], ['3', None], ['-1', '4']]
    >
    >Basically, I want to split each string into two items, substituting
    >None when no second item is specified in the string. (As you can see,
    >in my strings, the items are delimited by ':').
    >
    >It seems like a simple enough operation that I should be able to write
    >a list comprehension for it, but I can't figure out how... Any
    >suggestions?
    >
    >Steve


    Here's a pretty nasty approach:

    >>> lst = ['1', '1:2', '3', '-1:4']
    >>> splits = [(e.split(':') + [None])[:2] for e in lst]
    >>> splits

    [['1', None], ['1', '2'], ['3', None], ['-1', '4']]
    --

    Bob Follek
    Bob Follek, Oct 12, 2004
    #3
  4. Russell Blau <russblau <at> hotmail.com> writes:

    > >>> lst = ['1', '1:2', '3', '-1:4']
    > >>> splits = [':' in item and item.split(':', 1) or [item, None]

    > for item in lst]
    > >>> splits

    > [['1', None], ['1', '2'], ['3', None], ['-1', '4']]


    Oooh. Pretty. =)

    What if I want to convert my splits list to:

    [[1, None], [1, 2], [3, None], [-1, 4]]

    where I actually call int on each of the non-None items? Obviously I could
    extend your example to:

    >>> lst = ['1', '1:2', '3', '-1:4']
    >>> splits = [':' in item and [int(x) for x in item.split(':', 1)]

    .... or [int(item), None]
    .... for item in lst]
    >>> splits

    [[1, None], [1, 2], [3, None], [-1, 4]]

    But that's getting to be a bit more work than looks good to me in a list
    comprehension. I thought about doing it in two steps:

    >>> splits = [':' in item and item.split(':', 1) or [item, None]

    .... for item in lst]
    >>> splits = [[int(i), p is not None and int(p) or p]

    .... for i, p in splits]
    >>> splits

    [[1, None], [1, 2], [3, None], [-1, 4]]

    This looks decent to me, but if you see a better way, I'd love to hear about
    it. =)

    Thanks again!

    Steve
    Steven Bethard, Oct 13, 2004
    #4
  5. Steven Bethard <steven.bethard <at> gmail.com> writes:
    > >>> splits = [':' in item and item.split(':', 1) or [item, None]

    > ... for item in lst]
    > >>> splits = [[int(i), p is not None and int(p) or p]

    > ... for i, p in splits]
    > >>> splits

    > [[1, None], [1, 2], [3, None], [-1, 4]]


    So I realized that this doesn't quite work if the second item in a split is 0 -
    - you'll end up with None instead of 0.

    Steve
    Steven Bethard, Oct 13, 2004
    #5
  6. Steven Bethard

    Martin Maney Guest

    Steven Bethard <> wrote:
    >>>> lst = ['1', '1:2', '3', '-1:4']
    >>>> splits = []
    >>>> for s in lst:

    > .... pair = s.split(':')
    > .... if len(pair) != 2:
    > .... pair.append(None)
    > .... splits.append(pair)
    > ....
    >>>> splits

    > [['1', None], ['1', '2'], ['3', None], ['-1', '4']]


    > Basically, I want to split each string into two items, substituting
    > None when no second item is specified in the string. (As you can see,
    > in my strings, the items are delimited by ':').


    Ah!

    >>> lst = ['1', '1:2', '3', '-1:4']
    >>> [ (x.split(':') + [None])[:2] for x in lst]

    [['1', None], ['1', '2'], ['3', None], ['-1', '4']]

    Handles both single-element and more-than-two-element strings. Doesn't
    crash on empty strings, but the result probably isn't useful:

    >>> [ (x.split(':') + [None])[:2] for x in ['1', '1:2', '3', '-1:4', '']]

    [['1', None], ['1', '2'], ['3', None], ['-1', '4'], ['', None]]

    You might also enjoy this variation

    >>> [ (map(int, x.split(':')) + [None])[:2] for x in lst]

    [[1, None], [1, 2], [3, None], [-1, 4]]

    Since I saw you mention wanting that later, I think. Didn't see any
    replies quite the same as this (but I didn't troll through the rest of
    the spool looking for possible unthreaded replies).

    --
    One discharges fancy homunculi from one's scheme
    by organizing armies of idiots to do the work. -- Dennett
    Martin Maney, Oct 14, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Ericson
    Replies:
    0
    Views:
    423
    John Ericson
    Jul 19, 2003
  2. Mark
    Replies:
    0
    Views:
    439
  3. John Dibling
    Replies:
    0
    Views:
    411
    John Dibling
    Jul 19, 2003
  4. Debajit Adhikary
    Replies:
    17
    Views:
    680
    Debajit Adhikary
    Oct 18, 2007
  5. Vedran Furac(
    Replies:
    4
    Views:
    322
    Marc 'BlackJack' Rintsch
    Dec 19, 2008
Loading...

Share This Page