Search code examples
python-3.xpython-3.8proofany

Using any/all with proof or examples


Came upon the need for a proof for when I use my any statement. Need to rewrite non-standardized product names from free-text fields.

dict1 = {'product1': 'Product_1',
         'prod1': 'Product_1',
         'produc1': 'Product_1'}
list1 = ['Product1', 'Product_1', 'ProDuc1']

list2 = []
for product in list1:
  if any(product.lower() in nonstandard for nonstandard in dict1):
    for bad_product_name in dict1:
      if product.lower() in bad_product_name:
        list2.append(dict1[bad_product_name])
  else:
    list2.append(product)

list2  # -> ['Product_1', 'Product_1', 'Product_1']

The need/use case for the any statement comes from wanting to avoid extra processing when it's unnecessary (albeit only a few more lines of code).


Solution

  • The any() from the question could be omitted but I had a use case for it and didn't find a similar SO question so I'm putting one out there in hopes it may help someone else (who isn't aware of the walrus)!

    With the creation of the walrus operator, :=, in python 3.8 (i.e. Python 3.8+ is a requirement) there are two ways to achieve the same result, 1 is easier to read/follow than the other.

    list2 = [dict1[tester] 
             if any(
               True for nonstandard in dict1
               if (tester := product.lower()) in nonstandard
             )
             else product
             for product in list1]
    # vs.
    list2 = []
    for product in list1:
      if any(True for nonstandard in dict1 if (tester := product.lower()) in nonstandard):
        list2.append(dict1[tester])
      else:
        list2.append(product)
    
    list2  # -> ['Product_1', 'Product_1', 'Product_1']
    

    There are specific points in the any() generator where the walrus can't be used so for simpler implementations, here are other formattings:

    # arbitrary statements not achieving anything - just demonstrating principles
    any(prod for (tester := prod) in list1 if prod)  # invalid
    any((tester := prod) for prod in list1)  # valid
    any(product for product in list1 if (tester := product)  # valid
    any(tester if (tester := prod) else prod.lower() for prod in list1)  # valid
    

    Note the placement of the walrus in the above examples would work in a similar list comprehension

    With some small modifications, this could be taken a step further to do a str.replace() and have multiple replaces for each word in list1 - similar to how pandas.replace() or other re.sub() implementations work but it's all native to Python's standard library so no need for imports.