## Thursday, March 26, 2009

### Booleans, ternary operators, and max

I ran into a situation today that initially stumped me. I needed to take a list of unknown size, check each item in the list to see if it could be found in a line of text, and return a single `True` or `False` if any one item in the list matched that check. Oh, and if the list was empty, that had to be addressed appropriately as well. And I wanted to do it in the smallest way possible.

Originally I'd hacked together a short four or five line function that did the job. However, after coming back to the code for some other updates, I noticed that said function was only being called once, so I began looking for ways to nix that function and do the job more directly. Part of the challenge was that this comparison I needed to do was part of an existing `if` statement, and it had to remain so due to the way the rest of the code worked. In short, the comparison went like this (in pseudo-Python):

`thisList = ["list", "of", "unknown", "length"]if not ":" in line and not anythingInThisList in line:  do stuffelse:  do other stuff`

The first thing I tried to figure out was a way to get a single `True` or `False` out of a list of various Boolean values. On a whim, I tried to use the built-in `max` function. I'd used `max` before in standard numeric comparisons, but never with Booleans. Not surprisingly, it worked quite well.

`>>> max(True, False)True>>> max([False, False, True, False])True`

Getting the necessary Boolean list to pass to `max` was a no-brainer thanks to Python's list comprehensions. Here's an example that quickly shows if a given word contains any vowels:

`>>> vowels = ["a", "e", "i", "o", "u"]>>> max([v in "sadness" for v in vowels])True>>> max([v in "shhhh" for v in vowels])False`

This process alone solved most of my problem. However, I couldn't always be sure that my list of things to look for would contain anything. The variable containing the list was set by an argument in a function definition, and that argument defaulted to `None` if no other data came through. That meant that I had to somehow force the output of the `max` comparison to `False` if the variable was `None`, or let it do its thing if not.

That got my thoughts going toward ternary operators. For those who don't know, many programming languages offer a condensed one-line shortcut for the standard `if-else` comparison, called a ternary operator. In short, it turns this:

`if statement:   doThiselse:   doThat`

into this:

`statement ? doThis : doThat`

Not long ago I dug around to see if Python supported anything like this, and sure enough it does (as of one of the more recent versions, but I forget which one), although it isn't in the standard documentation from what I could see. At any rate, the above example would look like this using Python's approach to the ternary operator:

`doThis if statement else doThat`

With that applied to my `max` comparison, the end result looked something like this (and I hope this all ends up on a single line in the blog post):

`# "line" is the line of text# "y" is either None or a list of items to find in "line"max([x in line for x in y] if y is not None else [False])`

The reason that `False` needs to be encapsulated inside a list is because `max` needs a list of items through which to iterate, even if that list only contains a single item.

It's also possible to generate the Boolean list using the `map` function and a lambda, and the code isn't that much longer:

`max(map(lambda x:x in line, y) if y is not None else [False])`