returning True, False or None

J

Jeremy Bowers

I have lists containing values that are all either True, False or None,
e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

Right now, my code looks like:

if True in lst:
return True
elif False in lst:
return False
else:
return None

Yes, I see the smell, you are searching the list multiple times. You
could bail out when you can:

seenFalse = False
for item in list:
if item: return True
if item is False: seenFalse = True
if seenFalse:
return False
return None

But I'd submit that if four item lists are your common case, that your
original code is significantly easier to understand what it is doing. This
can be alleviated with an appropriate comment on the chunk of code I gave
you, though.
 
J

Jeremy Bowers

[ False , False , True , None ]

False would be returned upon inspection of the first index, even
though True was in fact in the list. The same is true of the code of
Jeremy Bowers, Steve Juranich, and Jeff Shannon. As for Raymond
Hettinger, I can't even be sure ;)

Nope. To recall, my code was:

seenFalse = False
for item in list:
if item: return True
if item is False: seenFalse = True
if seenFalse:
return False
return None

So, turning that into a real function and not a sketch:

Python 2.3.4 (#1, Jan 25 2005, 21:29:33)
[GCC 3.4.3 (Gentoo Linux 3.4.3, ssp-3.4.3-0, pie-8.7.6.6)] on linux2
Type "help", "copyright", "credits" or "license" for more information..... seenFalse = False
.... for item in l:
.... if item: return True
.... if item is False: seenFalse = True
.... if seenFalse:
.... return False
.... return None
....
thingy([ False , False , True , None ]) True

The defense rests, your honor. :)

(I like the later use of "returnValue" and the reduce solution was cute
and quite educational (very appropriate here). I deliberately eschewed
fanciness, though.)
 
S

Steven Bethard

I have lists containing values that are all either True, False or None,
e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

Right now, my code looks like:

if True in lst:
return True
elif False in lst:
return False
else:
return None

This has a light code smell for me though -- can anyone see a simpler
way of writing this?

STeVe
 
A

Alex Martelli

Steven Bethard said:
I have lists containing values that are all either True, False or None,
e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

Right now, my code looks like:

if True in lst:
return True
elif False in lst:
return False
else:
return None

This has a light code smell for me though -- can anyone see a simpler
way of writing this?

What about...:

for val in lst:
if val is not None:
return val
return None

or the somewhat fancy/clever:

for val in (x for x in lst if x is not None):
return val
return None


Alex
 
R

Raymond Hettinger

"Steven Bethard"
For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False. . . .
Right now, my code looks like:

if True in lst:
return True
elif False in lst:
return False
else:
return None

This has a light code smell for me though -- can anyone see a simpler
way of writing this?


return max(lst)


Raymond Hettinger
 
S

Steve Holden

Steven said:
I have lists containing values that are all either True, False or None,
e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

Right now, my code looks like:

if True in lst:
return True
elif False in lst:
return False
else:
return None

This has a light code smell for me though -- can anyone see a simpler
way of writing this?

STeVe

That code looks like a pretty solid implementation of the spec to me.
There isn't a strict need for the last else, of course, which may be the
smell you detect.

If you wanted to get clever you could write something like

for i in True, False:
if i in lst:
return i
return False

but frankly I think that's more obscure, and saves you pretty much nothing.

regards
Steve
 
M

Michael Spencer

Steven said:
I have lists containing values that are all either True, False or None,
e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

Right now, my code looks like:

if True in lst:
return True
elif False in lst:
return False
else:
return None

This has a light code smell for me though -- can anyone see a simpler
way of writing this?

STeVe

max(lst) ;-)

Michael
 
M

Mick Krippendorf

Steven said:
I have lists containing values that are all either True, False or
None, e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.
Try:

Mick.
 
B

Brian van den Broek

Alex Martelli said unto the world upon 2005-02-04 13:02:
I have lists containing values that are all either True, False or None,
e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

Right now, my code looks like:
This has a light code smell for me though -- can anyone see a simpler
way of writing this?


What about...:

for val in lst:
if val is not None:
return val
return None

or the somewhat fancy/clever:

for val in (x for x in lst if x is not None):
return val
return None


Alex

These don't do what the OP desired.

..>>> test_case = [False, True, True, True ]
..>>> def alexs_funct(lst):
.. for val in lst:
.. if val is not None:
.. return val
.. return None
False

But, by the 'spec', it ought return True.

Best,

Brian vdB
A mere newbie, quite pleased with himself for finding a problem with
'bot code -- next scheduled to occur mid 2011 :)
 
P

Peter Otten

Steven said:
I have lists containing values that are all either True, False or None,
e.g.:

[True, None, None, False]
[None, False, False, None ]
[False, True, True, True ]
etc.

For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

Right now, my code looks like:

if True in lst:
return True
elif False in lst:
return False
else:
return None

This has a light code smell for me though -- can anyone see a simpler
way of writing this?

An attempt to short-circuit if possible:

def tristate(iterable):
it = iter(iterable)
for item in it:
if item is not None:
return item or True in it

Not as elegant as max(), but makes me wonder whether a max() that accepts an
additional upper_bound argument and returns upper_bound as soon as it
encounters a value >= upper_bound would be worth the effort.

Peter
 
S

Steven Bethard

Fredrik said:
too clever. boolean > None isn't guaranteed by the language specification:

Yup. I thought about mentioning that for anyone who wasn't involved in
the previous thread discussing this behavior, but I was too lazy. ;)
Thanks for pointing it out again.

This implementation detail was added in Python 2.1a1, with the following
note[1]:

"The outcome of comparing non-numeric objects of different types is
not defined by the language, other than that it's arbitrary but
consistent (see the Reference Manual). An implementation detail changed
in 2.1a1 such that None now compares less than any other object. Code
relying on this new behavior (like code that relied on the previous
behavior) does so at its own risk."

Steve

[1] http://www.python.org/2.1/NEWS.txt
 
J

Jeff Shannon

Jeremy said:
Yes, I see the smell, you are searching the list multiple times. You
could bail out when you can:

seenFalse = False
for item in list:
if item: return True
if item is False: seenFalse = True
if seenFalse:
return False
return None

I'd modify this approach slightly...

def tfn(lst):
answer = None
for item in lst:
if item is True: return True
if item is False: answer = False
return answer

But yeah, the original, straightforward way is probably enough clearer
that I wouldn't bother with anything else unless lists might be long
enough for performance to matter.

Jeff Shannon
Technician/Programmer
Credit International
 
R

Raymond Hettinger

"Steven Bethard"
For a given list:
* If all values are None, the function should return None.
* If at least one value is True, the function should return True.
* Otherwise, the function should return False.

One more approach, just for grins:

s = set(lst)
return True in s or s == set([None]) and None


Raymond Hettinger
 
D

Daniel Bickett

I'm seeing a consistent problem in most of these approaches.
Verbalized, the logic of the OP's original code reads as such:

If True is in the list *at all*, return True.
Otherwise, if False is in the list *at all*, return False.
Otherwise, return None.

So if we used Alex Martelli's code:
for val in lst:
if val is not None:
return val
return None

and the list was:

[ False , False , True , None ]

False would be returned upon inspection of the first index, even
though True was in fact in the list. The same is true of the code of
Jeremy Bowers, Steve Juranich, and Jeff Shannon. As for Raymond
Hettinger, I can't even be sure ;)

The original OP's code, on the other hand, inadvertently searches
through the list twice where once would have sufficed, causing a
needless performance pitfall. The following applies the OP's initial
logic while only iterating once:
falseExists = False
for item in items:
if item is True:
return True
elif item is False and not falseExists:
falseExists = True
if falseExists:
return False
l1 = [ True , None , None , False ]
l2 = [ None , False , False , None ]
l3 = [ False , True , True , True ]
boolhunt( l1 ) True
boolhunt( l2 ) False
boolhunt( l3 )
True

It isn't elegant or clever, but it gets the job done :)
 
M

Mick Krippendorf

Fredrik said:
too clever. boolean > None isn't guaranteed by the language
specification:

http://docs.python.org/ref/comparisons.html

"... objects of different types always compare unequal, and are
ordered consistently but arbitrarily. /.../ In the future, the
comparison rules for objects of different types are likely to
change. ..."

Then maybe like this:
... if e1 == None:
... return e2
... elif e2 == None:
... return e1
... else:
... return max(e1, e2)

Mick.
 
J

Jeff Shannon

Jeremy said:
[ False , False , True , None ]

False would be returned upon inspection of the first index, even
though True was in fact in the list. The same is true of the code of
Jeremy Bowers, Steve Juranich, and Jeff Shannon. As for Raymond
Hettinger, I can't even be sure ;)

Nope.

Indeed. Similarly for mine, which was really just a slight transform
of Jeremy's (setting a return variable directly, instead of setting a
flag that's later used to decide what to return):
.... answer = None
.... for item in lst:
.... if item is True: return True
.... if item is False: answer = False
.... return answer
....
>>> list = [False, False, True, None]
>>> tfn(list) 1
>>> list = [None, False, False, None]
>>> tfn(list) 0
>>> list = [None, None, None, None]
>>> print tfn(list) None
>>> >>>

The noted logical flaw *has* been present in a number of proposed
solutions, however.

The key point to note is that one *must* examine the entire list
*unless* you find a True; short-circuiting on False means that you may
miss a later True.

Jeff Shannon
Technician/Programmer
Credit International
 
M

Mick Krippendorf

Daniel said:
... falseExists = False
... for item in items:
... if item is True:
... return True
... elif item is False and not falseExists:
... falseExists = True
... if falseExists:
... return False



Or even shorter:
... result = None
... for item in items:
... if item:
... return True
... elif result is None and item is False:
... result = False
... return result


Or like the Melmacians would do it:
... result = None
... for item in items:
... if result:
... raise StopIteration
... elif item is not None:
... result = item
... yield result
>>> [item for item in boolgen(a_list)][-1]


Mick.
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top