split up a list by condition?

  • Thread starter Reinhold Birkenfeld
  • Start date
R

Reinhold Birkenfeld

Hi,

while writing my solution for "The python way?", I came across this fragment:

vees = [c for c in wlist[::-1] if c in vocals]
cons = [c for c in wlist[::-1] if c not in vocals]

So I think: Have I overlooked a function which splits up a sequence into two,
based on a condition? Such as

vees, cons = split(wlist[::-1], lambda c: c in vocals)

Reinhold
 
G

Grooooops

Reinhold,
Thanks for your response in the previous thread.
Yours is an interesting question. I haven't come up with a solution,
but I did realize that in the previous problem, the source 'word'
doesn't really need to stay intact...
So perhaps a solution along these lines?
.... if a[1] in vowels:
.... vees.append(wlist.pop(a[0]))

I don't know if it's possible to cram a 'pop' command into the single
line solution though.

I look forward to seeing other tricks to this end... :)
 
R

Raymond Hettinger

while writing my solution for "The python way?", I came across this fragment:
vees = [c for c in wlist[::-1] if c in vocals]
cons = [c for c in wlist[::-1] if c not in vocals]

So I think: Have I overlooked a function which splits up a sequence
into two, based on a condition

Trying to compress too much into one line is not "the python way" ;-)


vees, cons = [], []
for c in reversed(wlist):
if c in vocals:
vees.append(c)
else:
cons.append(c)
 
D

Duncan Booth

Reinhold said:
Hi,

while writing my solution for "The python way?", I came across this
fragment:

vees = [c for c in wlist[::-1] if c in vocals]
cons = [c for c in wlist[::-1] if c not in vocals]

So I think: Have I overlooked a function which splits up a sequence
into two, based on a condition? Such as

vees, cons = split(wlist[::-1], lambda c: c in vocals)

Reinhold

If you really are being charged by the number of newline characters in your
code you could write:
wlist = list('The quick brown fox')
vowels = 'aeiuo'
cons = []
vees = [ c for c in wlist if c in vowels or cons.append(c) ]
cons ['T', 'h', ' ', 'q', 'c', 'k', ' ', 'b', 'r', 'w', 'n', ' ', 'f', 'x']
vees ['e', 'u', 'i', 'o', 'o']
cons = []
vees = [ c for c in wlist[::-1] if c in vowels or cons.append(c) ]
cons ['x', 'f', ' ', 'n', 'w', 'r', 'b', ' ', 'k', 'c', 'q', ' ', 'h', 'T']
vees
['o', 'o', 'i', 'u', 'e']

but every penny you save writing a one liner will be tuppence extra on
maintenance.
 
R

Reinhold Birkenfeld

Raymond said:
while writing my solution for "The python way?", I came across this fragment:
vees = [c for c in wlist[::-1] if c in vocals]
cons = [c for c in wlist[::-1] if c not in vocals]

So I think: Have I overlooked a function which splits up a sequence
into two, based on a condition

Trying to compress too much into one line is not "the python way" ;-)

I know (there is a Guido quote about this, I just lost the source...)
vees, cons = [], []
for c in reversed(wlist):
if c in vocals:
vees.append(c)
else:
cons.append(c)

Well, I've found a uglier solution,

vees, cons = [], []
[(vees, cons)[ch in vocals].append(ch) for ch in wlist]

Reinhold
 
R

Reinhold Birkenfeld

Duncan said:
Reinhold said:
Hi,

while writing my solution for "The python way?", I came across this
fragment:

vees = [c for c in wlist[::-1] if c in vocals]
cons = [c for c in wlist[::-1] if c not in vocals]

So I think: Have I overlooked a function which splits up a sequence
into two, based on a condition? Such as

vees, cons = split(wlist[::-1], lambda c: c in vocals)

Reinhold

If you really are being charged by the number of newline characters in your
code you could write:
[...]

but every penny you save writing a one liner will be tuppence extra on
maintenance.

This is clear. I actually wanted to know if there is a function which I
overlooked which does that, which wouldn't be a maintenance nightmare at all.

Reinhold
 
G

Grooooops

vees, cons = [], []
[(vees, cons)[ch in vocals].append(ch) for ch in wlist]

Wow, that's horribly twisted Reinhold...
I spent about an hour last night trying something similar, to no end...
:)

Neat tricks people...
I like Duncan's use of "or" to solve it.
I didn't see that in the python docs on list comprehension.
Very cool.

There is a special place in my heart for obfuscated Python,
but of course, not in production code if there is a clearer solution
available.
 
P

Paul McGuire

Re-run this with the input string "The quick brown fox is named
'Aloysius'." and we discover that 'A', 'y', "'" and '.' are also
consonants. (Actually, this is bug-compatible with the OP's original
example.)

-- Paul
 
A

Andrew Dalke

Reinhold said:
So I think: Have I overlooked a function which splits up a sequence
into two, based on a condition? Such as

vees, cons = split(wlist[::-1], lambda c: c in vocals)
This is clear. I actually wanted to know if there is a function which I
overlooked which does that, which wouldn't be a maintenance nightmare at
all.

Not that I know of, but if there is one it should be named
"bifilter", or "difilter" if you prefer Greek roots. :)


def bifilter(test, seq):
passes = []
fails = []
for term in seq:
if test(term):
passes.append(term)
else:
fails.append(term)
return passes, fails

bifilter("aeiou".__contains__, "This is a test") (['i', 'i', 'a', 'e'], ['T', 'h', 's', ' ', 's', ' ', ' ', 't', 's', 't'])

Another implementation, though in this case I cheat because I
do the test twice, is
.... seq1, seq2 = tee(seq)
.... return ifilter(test, seq1), ifilterfalse(test, seq2)
....
bifilter("aeiou".__contains__, "This is another test")
map(list, _) [['i', 'i', 'a', 'o', 'e', 'e'], ['T', 'h', 's', ' ', 's', ' ', 'n', 't', 'h', 'r', ' ', 't', 's', 't']]


Andrew
(e-mail address removed)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,241
Messages
2,571,219
Members
47,850
Latest member
StewartTha

Latest Threads

Top