Determine a percentage of common items in two lists

In this snippet, we are taking two lists (I imagine this would work with multiples as well) and we are determining a percentage of the items that are in both lists.

Here is the code:

def check_ingredient_match(recipe, ingredients):
    matched = 0
    missing = []
 
    for item in recipe:
        if item in ingredients:
            matched += 1
        else:
            missing.append(item)
 
    percentage = (matched / len(recipe)) * 100
    return round(percentage, 2), missing

How does this work?

set the stage

def check_ingredient_match(recipe, ingredients):

Here, you are creating a function called check_ingredient_match and the input in this case happens to be two lists, one is the recipe list. That is the things that you need to have on hand. The other is ingredients, which is the items you actually have. So what are we going to do to compare them?

build the base

    matched = 0
    missing = []

We are going to have to work with these variables later, so we need to set them up now. The first is matched, which is the count of how many items between the two lists were the same, meaning in this case that you had the required recipe item in your handy ingredients. The missing parameter is clearly what you did not have.

We set matched to 0 because you haven’t compared yet, so there are no matches yet. The missing is a list, the list you will populate with the things that are not in both lists.

making the sausage

    ​for item in recipe:
        ​if item in ingredients:
            matched += 1
        ​else:
            missing.append(item)

Starting with the first line, for item in recipe, we pull the items for the list recipe. Once we have them, we compare those to the ones in ingredients with the line if item in ingredients.

If they match, the directive matched += 1 will increment the matched pointer we set before by 1.

Otherwise, if they in fact are discrete and are not in both lists, they are considered else.

This is where missing.append(item) comes in. missing is our list of the mentioned items that aren’t in both lists, and we want to know what those are, so we append(item), or we add that missing item to the missing list.

let’s do some math

percentage = (matched / len(recipe)) * 100

This is creating a percentage variable, that we’ll use to hold the final value, and this is where we get our head around things.

The math will look like this: We are taking the post-counted matched counter that says how many items we found that matched. Then, we’ll divide that into the total count of items in the recipe list. Once we have that result, it is multiplied by 100 in order to get the final percentage.

make it pretty

return round(percentage, 2), missing

We know what return does, it gives the result to the code again. But what exactly are we giving here?

In this case, we are rounding with round, which means we are going to take the result of percentage and round it to two digits with the 2.

Then, by returning the missing list, we print the contents of the items that are in the recipe list, but not in the ingredients list.

How it looks when tested

Inputs: 
- Recipe: ['Dragon Scale', 'Unicorn Hair', 'Phoenix Feather', 'Troll Tusk', 'Mandrake Root', 'Griffin Feather', 'Elf Dust', 'Goblin Ear'] 
- Ingredients: ['Dragon Scale', 'Phoenix Feather', 'Mandrake Root', 'Griffin Feather', 'Elf Dust', 'Goblin Ear'] 
Expecting: (75.0, ['Unicorn Hair', 'Troll Tusk']) 
Actual: (75.0, ['Unicorn Hair', 'Troll Tusk']) 
Pass 
============= PASS ============== 
2 passed, 0 failed, 2 skipped

From this, you can see that there are 8 items in the recipe list in this case, and only 6 items in the ingredients list. Quick math in your head will verify that you do in fact only have 75% of the ingredients.

Now you should understand how this works, and how to adapt it to your usages.