Python: Searchable dictionary within a dictionary? - python

I'm new to Python, not used to handling this kind of stuff.
The code I've written:
search = str.lower(raw_input("What are you looking for?" + " " ))
knowledge = {"apple": 123, "test" : "cats"}
def return_the_input(search):
if search in knowledge:
print knowledge.get(search)
else:
print "No."
return_the_input(search)
So what I'd like for it to do would be to ask you what you're looking for (apple), then apple would display something similar to a Ls command in unix. So it would look like this:
"What are you looking for?" --input apple. Apple would then print out other values, like
Butter
Sauce
Snacks
And would then ask "What next?" --input butter
And all of the information I have on apple butter would display.
So do I set this up in the code as
knowledge = {"apple":{"butter": "info on butter here", "sauce": "info on sauce here"}, "cats":{et cetera}}
And then act upon that somehow to get the formatting I want? I assume maybe with some kind of For loop, or just print statements?

Your idea would work. But then what if an item belonged under two categories? A better solution would be to store all of the pieces of knowledge and then have a data structure mapping search words to knowledge.
knowledge = [
[("apple", "butter"), "made from cooked down apple sauce"],
[("peanut", "butter"), "made from crushed peanuts"],
]
def make_terms_from_knowledge(info):
search_terms = {}
for n, item in enumerate(info):
for i in item[0]:
search_terms.setdefault(i, []).append(n)
return search_terms
terms = make_terms_from_knowledge(knowledge)
print terms["butter"]
for entry in terms["butter"]:
print knowledge[entry][1]
You will need to regenerate terms whenever knowledge changes length. This is very simple but should get you thinking down other paths plus show some Python tips.

Related

How do I find predefined words in a wall of text?

I am thinking of an idea that I want to do for my ownself project during this quarantine phase . I am learning python by myself so I thought maybe I could see what I can do.
Question: I want to decipher large, but irregular count text and I want to find words in them, think of it like finding words. I may know the words that I find.
For example, I want to find
fruits = ["banana", "apples", "oranges"]
in
Text = "sdasfdsfdscbananassafdfdsafscdfbfnhujuyjhtrgrfeaddaDWEAFSERGRapplesfsgrgvscfaefcwecfrvtbhytofsdasrangesdaeubfuenijnzcjbvnkMDLOwkdpoaDPOSKPKFEOFJsfjuf"
How could I do that?
Also its my 1st time posting here so I am not really confident about this community.
sorry & thank you
Loop through all the words you want to find and check if they're in your text
for fruit in fruits:
if fruit in Text:
print(f"Found {fruit}")
Or, using a list comprehension:
found = [fruit for fruit in fruits if fruit in Text]
print(found)
fruits = ["banana", "apples", "oranges"]
text = "sdasfdsfdscbananassafdfdsafscdfbfnhujuyjhtrgrfeaddaDWEAFSERGRapplesfsgrgvscfaefcwecfrvtbhytofsdasrangesdaeubfuenijnzcjbvnkMDLOwkdpoaDPOSKPKFEOFJsfjuf"
for fruit in fruits:
if fruit in text:
print(fruit, "True")
else:
print(fruit, "False")

What is the most pythonic way to iterate through a long list of strings and structure new lists from that original list?

I have a large list of strings of song lyrics. Each element in the list is a song, and each song has multiple lines and some of those lines are headers such as '[Intro]', '[Chorus]' etc. I'm trying to iterate through the list and create new lists where each new list is comprised of all the lines in a certain section like '[Intro]' or '[Chorus]'. Once I achieve this I want to create a Pandas data frame where each row are all the song lyrics and each column is that section(Intro, Chorus, Verse 1, etc.) of the song. Am I thinking about this the right way? Here's an example of 1 element in the list and my current partial attempt to iterate and store:
song_index_number = 0
line_index_in_song = 0
intro = []
bridge = []
verse1 = []
prechorus = []
chorus = []
verse2 = []
verse3 = []
verse4 = []
verse5 = []
outro = []
lyrics_by_song[30]
['[Intro]',
'(Just the two of us, just the two of us)',
'Baby, your dada loves you',
"And I'ma always be here for you",
'(Just the two of us, just the two of us)',
'No matter what happens',
"You're all I got in this world",
'(Just the two of us, just the two of us)',
"I would never give you up for nothin'",
'(Just the two of us, just the two of us)',
'Nobody in this world is ever gonna keep you from me',
'I love you',
'',
'[Verse 1]',
"C'mon Hai-Hai, we goin' to the beach",
'Grab a couple of toys and let Dada strap you in the car seat',
"Oh, where's Mama? She's takin' a little nap in the trunk",
"Oh, that smell? Dada must've runned over a skunk",
"Now, I know what you're thinkin', it's kind of late to go swimmin'",
"But you know your Mama, she's one of those type of women",
"That do crazy things, and if she don't get her way, she'll throw a fit",
"Don't play with Dada's toy knife, honey, let go of it (No)",
"And don't look so upset, why you actin' bashful?",
"Don't you wanna help Dada build a sandcastle? (Yeah)",
'And Mama said she wants to show you how far she can float',
"And don't worry about that little boo-boo on her throat",
"It's just a little scratch, it don't hurt",
"Her was eatin' dinner while you were sweepin'",
'And spilled ketchup on her shirt',
"Mama's messy, ain't she? We'll let her wash off in the water",
"And me and you can play by ourselves, can't we?",
'',
'[Chorus]',
'Just the two of us, just the two of us',....
for line in lyrics_by_song:
if lyrics_by_song == '[Intro]':
intro.append(line)
Refer to python's doc: https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions
you could also use this
Intro = lyrics_by_song[lyrics_by_song.index('[Intro]'):lyrics_by_song.index('something_else')]
See top answer here: Understanding slice notation

Templates with argument in string formatting

I'm looking for a package or any other approach (other than manual replacement) for the templates within string formatting.
I want to achieve something like this (this is just an example so you could get the idea, not the actual working code):
text = "I {what:like,love} {item:pizza,space,science}".format(what=2,item=3)
print(text)
So the output would be:
I love science
How can I achieve this? I have been searching but cannot find anything appropriate. Probably used wrong naming terms.
If there isnt any ready to use package around I would love to read some tips on the starting point to code this myself.
I think using list is sufficient since python lists are persistent
what = ["like","love"]
items = ["pizza","space","science"]
text = "I {} {}".format(what[1],items[2])
print(text)
output:
I love science
My be use a list or a tuple for what and item as both data types preserve insertion order.
what = ['like', 'love']
item = ['pizza', 'space', 'science']
text = "I {what} {item}".format(what=what[1],item=item[2])
print(text) # I like science
or even this is possible.
text = "I {what[1]} {item[2]}".format(what=what, item=item)
print(text) # I like science
Hope this helps!
Why not use a dictionary?
options = {'what': ('like', 'love'), 'item': ('pizza', 'space', 'science')}
print("I " + options['what'][1] + ' ' + options['item'][2])
This returns: "I love science"
Or if you wanted a method to rid yourself of having to reformat to accommodate/remove spaces, then incorporate this into your dictionary structure, like so:
options = {'what': (' like', ' love'), 'item': (' pizza', ' space', ' science'), 'fullstop': '.'}
print("I" + options['what'][0] + options['item'][0] + options['fullstop'])
And this returns: "I like pizza."
Since no one have provided an appropriate answer that answers my question directly, I decided to work on this myself.
I had to use double brackets, because single ones are reserved for the string formatting.
I ended up with the following class:
class ArgTempl:
def __init__(self, _str):
self._str = _str
def format(self, **args):
for k in re.finditer(r"{{(\w+):([\w,]+?)}}", self._str,
flags=re.DOTALL | re.MULTILINE | re.IGNORECASE):
key, replacements = k.groups()
if not key in args:
continue
self._str = self._str.replace(k.group(0), replacements.split(',')[args[key]])
return self._str
This is a primitive, 5 minute written code, therefore lack of checks and so on. It works as expected and can be improved easly.
Tested on Python 2.7 & 3.6~
Usage:
test = "I {{what:like,love}} {{item:pizza,space,science}}"
print(ArgTempl(test).format(what=1, item=2))
> I love science
Thanks for all of the replies.

Search multiple keywords in string

I'm looking for a way to complete this task as efficient as possible.
Here is how I want it to work.Say user inputs
"My screen is broken"
The script finds the two keywords "screen" and "broken" and then prints an appropriate string. Being a noob I thought I might be able to use a dictionary like this
{"screen", "broken", "smashed":"use a repair kit"}
Then I would just search all the keys in the dictionary.
But upon further research it seems this is not possible.
So what would be the best way to do this? I thought maybe sql but I was wondering if there was a better way which would involve just python.Thanks
If you are just looking for "screen" and "broken", something like this can work.
sentence = "My screen is broken"
keys = ["screen", "broken"]
if all(i in sentence for i in keys):
print "Use a repair kit"
Building on zyxue's answer, you could make it check for certain values but not all of them. This will work with your above code, but you can nest multiple tuples together if you'd like to group other names.
sentence = "My screen is smashed"
solution_dict = {}
solution_dict[("screen", ("broken", "smashed"))] = "use a repair kit"
#If value is a tuple, run function on every value and return if there are any matches
#If not, check the word is part of the sentence
def check_match(sentence_words, keyword):
if isinstance(keyword, tuple):
return any([check_match(sentence_words, i) for i in keyword])
return keyword in sentence_words
#Make sure each value in the main tuple has a match
sentence_words = [i.lower() for i in sentence.split()]
for k,v in solution_dict.iteritems():
if all(check_match(sentence_words, i) for i in k):
print v
So you'll get results like this:
>>> sentence = "My screen is smashed"
use a repair kit
>>> sentence = "My screen is smashed and broken"
use a repair kit
>>> sentence = "My screen is broken"
use a repair kit
>>> sentence = "My phone is broken"
(nothing)
To work with phone too, along with iphone and android, you could set it like this, having iphone and android in another tuple makes no difference but just groups it a little better. solution_dict[(("screen", "phone", ("android", "iphone")), ("broken", "smashed"))] = "use a repair kit"
Dictionary keys need to be immutable, you could use a tuple, e.g.
# {("screen", "broken"): "use a repair kit"}
# input is a keyword in Python, so use input_ instead
input_ = input_.split()
if 'screen' in input_ and 'broken' in input_:
return "use a repair kit"
solutions = [{'keywords': ['screen', 'broken', 'smashed'], 'solution': 'use a repair kit'}]
s = 'My screen is broken'
words = set(s.lower().split(' '))
print '\n'.join([x.get('solution') for x in solutions if words & set(x.get('keywords', []))])

Manipulating strings in python - concentrating on part of a user's input

resp = raw_input("What is your favorite fruit?\n")
if "I like" in resp:
print "%s" - "I like" + " is a delicious fruit." % resp
else:
print "Bubbles and beans."
OK I know this code doesn't work, and I know why. You can't subtract strings from each other like numbers.
But is there a way to break apart a string and only use part of the response?
And by "is there a way" I really mean "how," because anything is possible in programming. :D
I'm trying to write my first chatterbot from scratch.
One option would be to simply replace the part that you want to remove with an empty string:
resp = raw_input("What is your favorite fruit?\n")
if "I like" in resp:
print "%s is a delicious fruit." % (resp.replace("I like ", ""))
else:
print "Bubbles and beans."
If you want to look into more advanced pattern matching to grab out more specific parts of strings via flexible patterns, you might want to look into regular expressions.
# python
"I like turtles".replace("I like ","")
'turtles'
Here's a way to do it with regular expressions:
In [1]: import re
In [2]: pat = r'(I like )*(\w+)( is a delicious fruit)*'
In [3]: print re.match(pat, 'I like apples').groups()[1]
apples
In [4]: print re.match(pat, 'apple is a delicious fruit').groups()[1]
apple
Can you just strip "I like"?
resp.strip("I like")
be careful of case sensitivity though.

Categories