Connecting Tech Pros Worldwide Forums | Help | Site Map

list comprehension for splitting strings into pairs

Steven Bethard
Guest
 
Posts: n/a
#1: Jul 18 '05
Here's what I'm doing:
[color=blue][color=green][color=darkred]
>>> lst = ['1', '1:2', '3', '-1:4']
>>> splits = []
>>> for s in lst:[/color][/color][/color]
.... pair = s.split(':')
.... if len(pair) != 2:
.... pair.append(None)
.... splits.append(pair)
....[color=blue][color=green][color=darkred]
>>> splits[/color][/color][/color]
[['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

Russell Blau
Guest
 
Posts: n/a
#2: Jul 18 '05

re: list comprehension for splitting strings into pairs


"Steven Bethard" <steven.bethard@gmail.com> wrote in message
news:mailman.4781.1097619107.5135.python-list@python.org...[color=blue]
> Here's what I'm doing:
>[color=green][color=darkred]
> >>> lst = ['1', '1:2', '3', '-1:4']
> >>> splits = []
> >>> for s in lst:[/color][/color]
> ... pair = s.split(':')
> ... if len(pair) != 2:
> ... pair.append(None)
> ... splits.append(pair)
> ...[color=green][color=darkred]
> >>> splits[/color][/color]
> [['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?[/color]

How's this?
[color=blue][color=green][color=darkred]
>>> lst = ['1', '1:2', '3', '-1:4']
>>> splits = [':' in item and item.split(':', 1) or [item, None] \[/color][/color][/color]
for item in lst][color=blue][color=green][color=darkred]
>>> splits[/color][/color][/color]
[['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.


Bob Follek
Guest
 
Posts: n/a
#3: Jul 18 '05

re: list comprehension for splitting strings into pairs


On Tue, 12 Oct 2004 16:11:45 -0600, Steven Bethard
<steven.bethard@gmail.com> wrote:
[color=blue]
>Here's what I'm doing:
>[color=green][color=darkred]
>>>> lst = ['1', '1:2', '3', '-1:4']
>>>> splits = []
>>>> for s in lst:[/color][/color]
>... pair = s.split(':')
>... if len(pair) != 2:
>... pair.append(None)
>... splits.append(pair)
>...[color=green][color=darkred]
>>>> splits[/color][/color]
>[['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[/color]

Here's a pretty nasty approach:
[color=blue][color=green][color=darkred]
>>> lst = ['1', '1:2', '3', '-1:4']
>>> splits = [(e.split(':') + [None])[:2] for e in lst]
>>> splits[/color][/color][/color]
[['1', None], ['1', '2'], ['3', None], ['-1', '4']]
--

Bob Follek
bob@codeblitz.com
Steven Bethard
Guest
 
Posts: n/a
#4: Jul 18 '05

re: list comprehension for splitting strings into pairs


Russell Blau <russblau <at> hotmail.com> writes:
[color=blue][color=green][color=darkred]
> >>> lst = ['1', '1:2', '3', '-1:4']
> >>> splits = [':' in item and item.split(':', 1) or [item, None][/color][/color]
> for item in lst][color=green][color=darkred]
> >>> splits[/color][/color]
> [['1', None], ['1', '2'], ['3', None], ['-1', '4']][/color]

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:
[color=blue][color=green][color=darkred]
>>> lst = ['1', '1:2', '3', '-1:4']
>>> splits = [':' in item and [int(x) for x in item.split(':', 1)][/color][/color][/color]
.... or [int(item), None]
.... for item in lst][color=blue][color=green][color=darkred]
>>> splits[/color][/color][/color]
[[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:
[color=blue][color=green][color=darkred]
>>> splits = [':' in item and item.split(':', 1) or [item, None][/color][/color][/color]
.... for item in lst][color=blue][color=green][color=darkred]
>>> splits = [[int(i), p is not None and int(p) or p][/color][/color][/color]
.... for i, p in splits][color=blue][color=green][color=darkred]
>>> splits[/color][/color][/color]
[[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
Guest
 
Posts: n/a
#5: Jul 18 '05

re: list comprehension for splitting strings into pairs


Steven Bethard <steven.bethard <at> gmail.com> writes:[color=blue][color=green][color=darkred]
> >>> splits = [':' in item and item.split(':', 1) or [item, None][/color][/color]
> ... for item in lst][color=green][color=darkred]
> >>> splits = [[int(i), p is not None and int(p) or p][/color][/color]
> ... for i, p in splits][color=green][color=darkred]
> >>> splits[/color][/color]
> [[1, None], [1, 2], [3, None], [-1, 4]][/color]

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

Martin Maney
Guest
 
Posts: n/a
#6: Jul 18 '05

re: list comprehension for splitting strings into pairs


Steven Bethard <steven.bethard@gmail.com> wrote:[color=blue][color=green][color=darkred]
>>>> lst = ['1', '1:2', '3', '-1:4']
>>>> splits = []
>>>> for s in lst:[/color][/color]
> .... pair = s.split(':')
> .... if len(pair) != 2:
> .... pair.append(None)
> .... splits.append(pair)
> ....[color=green][color=darkred]
>>>> splits[/color][/color]
> [['1', None], ['1', '2'], ['3', None], ['-1', '4']][/color]
[color=blue]
> 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 ':').[/color]

Ah!
[color=blue][color=green][color=darkred]
>>> lst = ['1', '1:2', '3', '-1:4']
>>> [ (x.split(':') + [None])[:2] for x in lst][/color][/color][/color]
[['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:
[color=blue][color=green][color=darkred]
>>> [ (x.split(':') + [None])[:2] for x in ['1', '1:2', '3', '-1:4', '']][/color][/color][/color]
[['1', None], ['1', '2'], ['3', None], ['-1', '4'], ['', None]]

You might also enjoy this variation
[color=blue][color=green][color=darkred]
>>> [ (map(int, x.split(':')) + [None])[:2] for x in lst][/color][/color][/color]
[[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
Closed Thread