Reputation: 383
So I have a dictionary that contains recipes. My current code is checking if a string exists in a value then add it to the counter. However I want it so that whenever the string is encountered in a dictionary value add one to the counter as there could be multiple occurrences of the same word in the value and I want to make sure I count all of them. Right now my code for counting the values in the dictionary is this:
if (token in str(value).lower()) and (key == 'title'):
title_c += 1
elif (token in str(value).lower()) and (key == 'categories'):
cat_c += 1
elif (token in str(value).lower()) and (key == 'ingredients'):
ing_c += 1
elif (token in str(value).lower()) and (key == 'directions'):
dire_c += 1
It checks the key for the dictionary and if the string appears in the value for that key and if it does add 1 to the counter. However if the token was 'banana' but the value for the title key for example was 'banana banana' it would add 1 to the title counter instead of 2. How could I change it for this?
My dictionary contains a list of recipes. Here is an example of a piece of data in the dictionary. My search is only looking through title, categories, ingredients and directions.
{
"title": "\"Blanketed\" Eggplant ",
"categories": [
"Tomato",
"Vegetable",
"Appetizer",
"Side",
"Vegetarian",
"Eggplant",
"Pan-Fry",
"Vegan",
"Bon App\u00e9tit"
],
"ingredients": [
"8 small Japanese eggplants, peeled",
"16 large fresh mint leaves",
"4 large garlic cloves, 2 slivered, 2 flattened",
"2 cups olive oil (for deep frying)",
"2 pounds tomatoes",
"7 tablespoons extra-virgin olive oil",
"1 medium onion, chopped",
"6 fresh basil leaves",
"1 tablespoon dried oregano",
"1 1/2 tablespoons drained capers"
],
"directions": [
"Place eggplants on double thickness of paper towels. Salt generously. Let stand 1 hour. Pat dry with paper towels. Cut 2 deep incisions in each eggplant. Using tip of knife, push 1 mint leaf and 1 garlic sliver into each incision.",
"Pour 2 cups oil into heavy medium saucepan and heat to 375\u00b0F. Add eggplants in batches and fry until deep golden brown, turning occasionally, about 4 minutes. Transfer eggplants to paper towels and drain.",
"Blanch tomatoes in pot of boiling water for 20 seconds. Drain. Peel tomatoes. Cut tomatoes in half; squeeze out seeds. Chop tomatoes; set aside.",
"Heat 4 tablespoons extra-virgin olive oil in large pot over high heat. Add 2 flattened garlic cloves; saut\u00e9 until light brown, about 3 minutes. Discard garlic. Add onion; saut\u00e9 until translucent, about 5 minutes. Add reduced to 3 cups, stirring occasionally, about 20 minutes.",
"Mix capers and 3 tablespoons extra-virgin olive oil into sauce. Season with salt and pepper. Reduce heat. Add eggplants. Simmer 5 minutes, spooning sauce over eggplants occasionally. Spoon sauce onto platter. Top with eggplants. Serve warm or at room temperature."
],
"rating": 3.75,
"calories": 1386.0,
"protein": 9.0,
"fat": 133.0
},
{
"title": "\"Bloody Mary\" Tomato Toast with Celery and Horseradish ",
"categories": [
"Condiment/Spread",
"Tomato",
"Appetizer",
"Kid-Friendly",
"Quick & Easy",
"Lunch",
"Spring",
"Summer",
"Vegetarian",
"Dairy Free",
"Peanut Free",
"Tree Nut Free",
"Soy Free",
"Kosher"
],
"ingredients": [
"1 lemon, zested, juiced",
"1/2 shallot, finely chopped",
"1 pound grape tomatoes, halved",
"2 tablespoons extra-virgin olive oil",
"1 tablespoon Sherry vinegar",
"1 teaspoon kosher salt",
"1 teaspoon freshly ground black pepper",
"1 teaspoon Worcestershire sauce",
"1/4 teaspoon cayenne pepper",
"5 tablespoons finely grated fresh horseradish, divided",
"2 celery stalks, thinly sliced",
"3 tablespoons coarsely chopped celery leaves",
"6 tablespoons mayonnaise",
"6 slices toasted rye bread"
],
"directions": [
"Combine lemon zest, lemon juice, shallot, tomatoes, oil, vinegar, salt, black pepper, Worcestershire sauce, cayenne, and 1 Tbsp. horseradish in a large bowl. Let marinate 10 minutes, then stir in celery stalks and leaves.",
"Meanwhile, combine mayonnaise and remaining 4 Tbsp. horseradish in a small bowl. Spread 1 Tbsp. horseradish-mayonnaise on each slice of rye. Top toasts evenly with tomato mixture."
],
"rating": 5.0,
"calories": 189.0,
"protein": 2.0,
"fat": 16.0
},
Upvotes: 0
Views: 2276
Reputation: 6474
I think you want exact word matches? You could use re.findall
for that with a regex and a defaultdict
for counting the word occurrences.
from collections import defaultdict
keys = [ "title", "categories", "ingredients", "directions"]
token = 'oil'
count = defaultdict(int)
for key in keys:
value = data[key]
if isinstance(value, str):
count[key] += len(re.findall(fr'\b{token}\b', value, flags=re.IGNORECASE))
elif (isinstance(value, list)):
count[key] += sum(len(re.findall(fr'\b{token}\b', line, flags=re.IGNORECASE)) for line in value)
print(count)
If you don't want to match against whole word, remove the word breaks (\b
) from the regex.
Upvotes: 0
Reputation: 23815
see below
data = {
"title": "\"Blanketed\" Eggplant ",
"categories": [
"Tomato",
"Vegetable",
"Appetizer",
"Side",
"Vegetarian",
"Eggplant",
"Pan-Fry",
"Vegan",
"Bon App\u00e9tit"
],
"ingredients": [
"8 small Japanese eggplants, peeled",
"16 large fresh mint leaves",
"4 large garlic cloves, 2 slivered, 2 flattened",
"2 cups olive oil (for deep frying)",
"2 pounds tomatoes",
"7 tablespoons extra-virgin olive oil",
"1 medium onion, chopped",
"6 fresh basil leaves",
"1 tablespoon dried oregano",
"1 1/2 tablespoons drained capers"
],
"directions": [
"Place eggplants on double thickness of paper towels. Salt generously. Let stand 1 hour. Pat dry with paper towels. Cut 2 deep incisions in each eggplant. Using tip of knife, push 1 mint leaf and 1 garlic sliver into each incision.",
"Pour 2 cups oil into heavy medium saucepan and heat to 375\u00b0F. Add eggplants in batches and fry until deep golden brown, turning occasionally, about 4 minutes. Transfer eggplants to paper towels and drain.",
"Blanch tomatoes in pot of boiling water for 20 seconds. Drain. Peel tomatoes. Cut tomatoes in half; squeeze out seeds. Chop tomatoes; set aside.",
"Heat 4 tablespoons extra-virgin olive oil in large pot over high heat. Add 2 flattened garlic cloves; saut\u00e9 until light brown, about 3 minutes. Discard garlic. Add onion; saut\u00e9 until translucent, about 5 minutes. Add reduced to 3 cups, stirring occasionally, about 20 minutes.",
"Mix capers and 3 tablespoons extra-virgin olive oil into sauce. Season with salt and pepper. Reduce heat. Add eggplants. Simmer 5 minutes, spooning sauce over eggplants occasionally. Spoon sauce onto platter. Top with eggplants. Serve warm or at room temperature."
],
"rating": 3.75,
"calories": 1386.0,
"protein": 9.0,
"fat": 133.0
}
keys = {'ingredients', 'directions'} # TODO: add more
counters = {k: 0 for k in keys}
token = 'eggplant'
for key in keys:
cnt = 0
for entry in data[key]:
cnt += entry.count(token)
counters[key] += cnt
print(counters)
output
{'ingredients': 1, 'directions': 7}
Upvotes: 0
Reputation: 16137
It looks to me like you have a list of dictionaries. If that's the case this should help. I've duplicated the recipe you posted and placed it into a list to demonstrate.
This will count the how many times every unique word appears in all of the categories you are interested in. Then you can just print the counter c
with the token you are interested in, or print c
by itself to see all of the counts.
from collections import Counter
from itertools import chain
recipe_dict = [{
"title": "\"Blanketed\" Eggplant ",
"categories": [
"Tomato",
"Vegetable",
"Appetizer",
"Side",
"Vegetarian",
"Eggplant",
"Pan-Fry",
"Vegan",
"Bon App\u00e9tit"
],
"ingredients": [
"8 small Japanese eggplants, peeled",
"16 large fresh mint leaves",
"4 large garlic cloves, 2 slivered, 2 flattened",
"2 cups olive oil (for deep frying)",
"2 pounds tomatoes",
"7 tablespoons extra-virgin olive oil",
"1 medium onion, chopped",
"6 fresh basil leaves",
"1 tablespoon dried oregano",
"1 1/2 tablespoons drained capers"
],
"directions": [
"Place eggplants on double thickness of paper towels. Salt generously. Let stand 1 hour. Pat dry with paper towels. Cut 2 deep incisions in each eggplant. Using tip of knife, push 1 mint leaf and 1 garlic sliver into each incision.",
"Pour 2 cups oil into heavy medium saucepan and heat to 375\u00b0F. Add eggplants in batches and fry until deep golden brown, turning occasionally, about 4 minutes. Transfer eggplants to paper towels and drain.",
"Blanch tomatoes in pot of boiling water for 20 seconds. Drain. Peel tomatoes. Cut tomatoes in half; squeeze out seeds. Chop tomatoes; set aside.",
"Heat 4 tablespoons extra-virgin olive oil in large pot over high heat. Add 2 flattened garlic cloves; saut\u00e9 until light brown, about 3 minutes. Discard garlic. Add onion; saut\u00e9 until translucent, about 5 minutes. Add reduced to 3 cups, stirring occasionally, about 20 minutes.",
"Mix capers and 3 tablespoons extra-virgin olive oil into sauce. Season with salt and pepper. Reduce heat. Add eggplants. Simmer 5 minutes, spooning sauce over eggplants occasionally. Spoon sauce onto platter. Top with eggplants. Serve warm or at room temperature."
],
"rating": 3.75,
"calories": 1386.0,
"protein": 9.0,
"fat": 133.0
},
{
"title": "\"Blanketed\" Eggplant ",
"categories": [
"Tomato",
"Vegetable",
"Appetizer",
"Side",
"Vegetarian",
"Eggplant",
"Pan-Fry",
"Vegan",
"Bon App\u00e9tit"
],
"ingredients": [
"8 small Japanese eggplants, peeled",
"16 large fresh mint leaves",
"4 large garlic cloves, 2 slivered, 2 flattened",
"2 cups olive oil (for deep frying)",
"2 pounds tomatoes",
"7 tablespoons extra-virgin olive oil",
"1 medium onion, chopped",
"6 fresh basil leaves",
"1 tablespoon dried oregano",
"1 1/2 tablespoons drained capers"
],
"directions": [
"Place eggplants on double thickness of paper towels. Salt generously. Let stand 1 hour. Pat dry with paper towels. Cut 2 deep incisions in each eggplant. Using tip of knife, push 1 mint leaf and 1 garlic sliver into each incision.",
"Pour 2 cups oil into heavy medium saucepan and heat to 375\u00b0F. Add eggplants in batches and fry until deep golden brown, turning occasionally, about 4 minutes. Transfer eggplants to paper towels and drain.",
"Blanch tomatoes in pot of boiling water for 20 seconds. Drain. Peel tomatoes. Cut tomatoes in half; squeeze out seeds. Chop tomatoes; set aside.",
"Heat 4 tablespoons extra-virgin olive oil in large pot over high heat. Add 2 flattened garlic cloves; saut\u00e9 until light brown, about 3 minutes. Discard garlic. Add onion; saut\u00e9 until translucent, about 5 minutes. Add reduced to 3 cups, stirring occasionally, about 20 minutes.",
"Mix capers and 3 tablespoons extra-virgin olive oil into sauce. Season with salt and pepper. Reduce heat. Add eggplants. Simmer 5 minutes, spooning sauce over eggplants occasionally. Spoon sauce onto platter. Top with eggplants. Serve warm or at room temperature."
],
"rating": 3.75,
"calories": 1386.0,
"protein": 9.0,
"fat": 133.0
}]
output = []
token = 'tomato'
for d in recipe_dict:
output.extend([x.lower().split() for x in d['categories'] + d['ingredients'] + d['directions']])
c = Counter(chain.from_iterable(output))
print(c[token])
Upvotes: 0
Reputation: 12826
You could try regular expressions like example below:
import re
value = "banana test banana"
token = "banana"
result = re.findall(token, value)
print(len(result))
Upvotes: 1