def make_category_filter(categories, blank=True):
categories = [category.strip() for category in categories]<EOL>categories.sort()<EOL>redundant_categories = set()<EOL>prefix_candidate = None<EOL>for category in categories:<EOL><INDENT>if prefix_candidate != Noneand category.find(prefix_candidate) == <NUM_LIT:0>:<EOL><INDENT>redundant_categories.add(category)<EOL><DEDENT>else:<EOL><INDENT>prefix_candidate = category<EOL><DEDENT><DEDENT>categories = [category for category in categories if category not in redundant_categories]<EOL>filters = [ops.bw_("<STR_LIT>", category) for category in categories]<EOL>if blank:<EOL><INDENT>filters.append(ops.blank_("<STR_LIT>"))<EOL><DEDENT>return ops.or_(*filters)<EOL>
Generates a dict representing a Factual filter matching any of the categories
passed. 

The resulting filter uses $bw "begins with" operators to return all matching
subcategories. Because of this, passing a top level category removes the need
to pass any of its subcategories. 

Conversely, specifying subcategories will not restrict results as expected
if a prefix of those subcategories is also provided. For example:
        make_category_filter(["Food & Beverage", "Food & Beverage > Cheese"])
is the same as 
        make_category_filter(["Food & Beverage"])

To minimize the size of the filters sent to Factual, make_category_filters 
identifies redundant subcategories and removes them. 

Note that because of this prefix matching, queries may return rows from unwanted
subcategories. It may be necessary for you to filter out these records after 
the Factual request. 

Specify blank=True to include items without a category set.