For loop outputting duplicates - python

a = {'1330': ('John', 'Gold', '1330'), "0001":('Matt', 'Wade', '0001'), '2112': ('Bob', 'Smith', '2112')}
com = {'6':['John Gold, getting no points', 'Matt played in this game? Didn\'t notice him','Love this shot!']}
comments_table = []
What I am trying to achieve with this replacer function is replace people's names in the strings found in com(dict) with the a code unique to them which is found in a(dict) via regex. Replacing the name with the code works, but adding that new string with the code instead of the name is where I am going wrong.
def replace_first_name():
for k,v in a.items():
for z, y in com.items():
for item in y:
firstname = a[k][0]
lastname = a[k][1]
full_name = firstname + ' ' + lastname
if firstname in item:
if full_name in item:
t = re.compile(re.escape(full_name), re.IGNORECASE)
comment = t.sub(a[k][2], item)
print ('1')
comments_table.append({
'post_id': z, 'comment': comment
})
continue
else:
t = re.compile(re.escape(firstname), re.IGNORECASE)
comment = t.sub(a[k][2], item)
print ('2')
comments_table.append({
'post_id':z, 'comment':comment
})
else:
print ('3')
if fuzz.ratio(item,item) > 90:
comments_table.append({
'post_id': z, 'comment': item
})
else:
pass
The problem is with the output as seen below:
[{'comment': '1330, getting no points', 'post_id': '6'}, {'comment': "Matt played in this game? Didn't notice him", 'post_id': '6'}, {'comment': 'Love this shot!', 'post_id': '6'}, {'comment': 'John Gold, getting no points', 'post_id': '6'}, {'comment': "Matt played in this game? Didn't notice him", 'post_id': '6'}, {'comment': 'Love this shot!', 'post_id': '6'}, {'comment': 'John Gold, getting no points', 'post_id': '6'}, {'comment': "0001 played in this game? Didn't notice him", 'post_id': '6'}, {'comment': 'Love this shot!', 'post_id': '6'}]
I don't want comments that already have their name replaced with the number to make their way into the final list. Therefore, I want my expected output to look like this:
[{'comment': '1330, getting no points', 'post_id': '6'},{'comment': '0001,played in this game? Didn\'t notice him', 'post_id': '6', {'comment':'Love this shot', 'post_id':'6'}]
I have looked into using an iterator by making y an iter_list, but I didn't get anywhere. Any help would be appreciated. Thanks!

Not sure why you are doing the regexp replace since you are checking if the first name/full name is present with in. Also not sure what the fuzz.ratio(item, item) thing in case 3 is supposed to do, but here's how you can do the simple/naive replacement:
#!/usr/bin/python
import re
def replace_names(authors, com):
res = []
for post_id, comments in com.items():
for comment in comments:
for author_id, author in authors.items():
first_name, last_name = author[0], author[1]
full_name = first_name + ' ' + last_name
if full_name in comment:
comment = comment.replace(full_name, author_id)
break
elif first_name in comment:
comment = comment.replace(first_name, author_id)
break
res.append({'post_id': post_id, 'comment': comment})
return res
a = {'1330': ('John', 'Gold', '1330'), "0001":('Matt', 'Wade', '0001'), '2112': ('Bob', 'Smith', '2112')}
com = {'6':['John Gold, getting no points', 'Matt played in this game? Didn\'t notice him','Love this shot!']}
for comment in replace_names(a, com):
print comment
Which produces this output:
{'comment': '1330, getting no points', 'post_id': '6'}
{'comment': "0001 played in this game? Didn't notice him", 'post_id': '6'}
{'comment': 'Love this shot!', 'post_id': '6'}
It's a bit tricky to understand what your intention is with the original code, but (one of) the reason(s) you are getting duplicates is that you are processing authors in the outher loop, which means you will process each comment one time for each author. By swapping the loop you ensure that each comment is processed only once.
You may also have intended to have a break where you have the continue, but I'm not entirely sure I understand how your original code is supposed to work.
The use of global variables is also a bit confusing.

Related

Searching for a specific value within a list of dictionaries

I need to be able to print all instances of a name within the list of dictionaries. I can't seem to be able to print them in the desired format. It also doesn't work when it's in lowercase and the name is in uppercase.
def findContactsByName(name):
return [element for element in contacts if element['name'] == name]
def displayContactsByName(name):
print(findContactsByName(name))
if inp == 3:
print("Item 3 was selected: Find contact")
name = input("Enter name of contact to find: ")
displayContactsByName(name)
When the name 'Joe' was put in the output is:
[{'name': 'Joe', 'surname': ' Miceli', 'DOB': ' 25/06/2002', 'mobileNo': ' 79444425', 'locality': ' Zabbar'}, {'name': 'Joe', 'surname': 'Bruh', 'DOB': '12/12/2131', 'mobileNo': '77777777', 'locality': 'gozo'}]
When the name 'joe':
[]
Expected output:
name : Joe
surname : Miceli
DOB : 25/06/2002
mobileNo : 79444425
locality : Zabbar
name : Joe
surname : Bruh
DOB : 12/12/2131
mobileNo : 77777777
locality : gozo
Change the first function to:
def findContactsByName(name):
return [element for element in contacts if element['name'].lower() == name.lower()]
To account for the differences in uppercase and lowercase, I've just converted the name in the dictionary and the entered name to lowercase during the comparison part alone.
To be able to print it in the format that you've specified you could make a function for the same as follows:
def printResult(result):
for d in result:
print(f"name: {d['name']}")
print(f"surname: {d['surname']}")
print(f"DOB: {d['DOB']}")
print(f"mobileNo: {d['mobileNo']}")
print(f"locality: {d['locality']}")
print()
result=findContactsByName("joe")
printResult(result)
I modified your program. Now you don't have to worry about the case and the output formatting.
contacts = [{'name': 'Joe',
'surname': ' Miceli', 'DOB': ' 25/06/2002', 'mobileNo': ' 79444425', 'locality': ' Zabbar'},
{'name': 'Joe', 'surname': 'Bruh', 'DOB': '12/12/2131', 'mobileNo': '77777777', 'locality': 'gozo'}]
def findContactsByName(name):
return [element for element in contacts if element['name'].lower() == name.lower()]
def displayContactsByName(name):
for i in range(len(findContactsByName(name))):
for j in contacts[i]:
print('{}: {}'.format(j, contacts[i][j]))
print('\n')
displayContactsByName('Joe')
Case issue can be solved by setting each side of the comparison to UPPERCASE or LOWERCASE.
return [element for element in contacts if element['name'].upper() == name.upper()]
For the format of the print statement you could use the json module:
import json
print(json.dumps( findContactsByName(name), sort_keys=True, indent=4))

Poem-writing and getting error for re-using the same function - Python

I'm doing this for a project. for which I need to do some web-scraping from Wikipedia specifically. This is the second phase of the project, so I need to create a poem about a person that the user enters (they have to have a Wikipedia page). I am using the Datamuse API for python to get some rhyming words which works really well.
Function ->
import requests
def get_10_rhyme_words(word):
key = 'https://api.datamuse.com/words?rel_rhy='
rhyme_words = []
rhymes = requests.get(key + word)
for i in rhymes.json()[0:10]:
rhyme_words.append(i['word'])
return rhyme_words
The criteria for the poem is that it needs to be at least 50 words long and make sense, so I came up with something like this:
“firstName” is nothing like “nameWord1”,
but it sounds a lot like “nameWord2”.
“genderPronoun” is a “professionFinal”,
Which sounds a lot like “professionWord1”.
“genderPronoun”’s favourite food might be waffles,
But it might also be “foodWord1”.
I now close this poem about the gorgeous “firstName”,
By saying “genderPronoun”’s name sounds a lot like “nameWord3”.
professionFinal was a variable used to describe their profession.
It works well for the name, but I get an IndexError every time I run it for the profession.
Name ->
The name poem
Here is a short poem on Serena:
Serena is nothing like hyena, but it sounds a lot like marina.
Profession ->
The Profession Poem (Error)
Here is a short poem on Serena:
Traceback (most recent call last): File "main.py", line 153, in <module> line4 = 'which sounds a lot like ' + random.choice(professionRhymes) + '.' File "/usr/lib/python3.8/random.py", line 290, in choice raise IndexError('Cannot choose from an empty sequence') from None IndexError: Cannot choose from an empty sequence
Here is the code I am using to make the poem ->
#Writing a poem about the person
firstName = person.split()[0]
foodWord = 'waffles'
print('\nHere is a short poem on {}:\n'.format(firstName))
nameRhymes = get_10_rhyme_words(firstName)
professionRhymes = get_10_rhyme_words(professionFinal)
foodRhymes = get_10_rhyme_words(foodWord)
if gender == 'Male':
heOrShe = 'He'
else:
heOrShe = 'She'
if gender == 'Male':
himOrHer = 'Him'
else:
himOrHer = 'Her'
line1 = firstName + ' is nothing like ' + random.choice(nameRhymes) + ','
line2 = 'but it sounds a lot like ' + random.choice(nameRhymes) + '.'
line3 = heOrShe + ' is a ' + professionFinal + ','
line4 = 'which sounds a lot like ' + random.choice(professionRhymes) + '.'
line5 = heOrShe + '\'s favourite food might be foodWord,'
line6 = 'but it might also be ' + random.choice(foodRhymes) + '.'
line7 = 'I now close this poem about the gorgeous {},'.format(firstName)
line8 = 'By saying {0}\'s name sounds a lot like {1}'.format(firstName, random.choice(nameRhymes))
print(line1)
print(line2)
print(line3)
print(line4)
print(line5)
print(line6)
print(line7)
print(line8)
**ignore the inconsistency and the lack of loops for printing each line
How do I make it so I don't get the error because frankly, I don't even know why I'm getting it...
Thanks!
(P.S.) Sorry for making it this long. Bye!
You should add a check for what the request returns. If it returns an empty list, it cannot be used as a random.choice() argument, since it requires a list with one or more item.
This part of this error
line4 = 'which sounds a lot like ' + random.choice(professionRhymes) + '.'
File "/usr/lib/python3.8/random.py",
line 290, in choice
raise IndexError('Cannot choose from an empty sequence')
from None IndexError: Cannot choose from an empty sequence
professionRhymes is probably returning an empty list.
Thanks to everyone that responded. It seems the consensus was enough to make me print the list and see that it comes up empty. Sadly, I am using repl and it doesn't have a debugger. But thanks guys, I found out the problem and will alter my poem to suit the needs of the program. As for the people asking the code, I only needed to check if their profession was that of a scientist, sportsperson, or politician. So I made a list, made a for loop check for keywords related to professions, then picked the right one. That is what professionFinal was.
Code:
#Finding their profession
#Declaring keywords for each profession
sportspersonKeywords = ['Sportsperson', 'Sportsman', 'Sportsman', 'Sports', 'Sport', 'Coach', 'Game', 'Olympics', 'Paralympics', 'Medal', 'Bronze', 'Silver', 'Gold', 'Player', 'sportsperson', 'sportsman', 'sportsman', 'sports', 'sport', 'coach', 'game', 'olympics', 'paralympics', 'medal', 'bronze', 'silver', 'gold', 'player', 'footballer', 'Footballer']
scientistKeywords = ['Scientist', 'Mathematician', 'Chemistry', 'Biology', 'Physics', 'Nobel Prize', 'Invention', 'Discovery', 'Invented', 'Discovered', 'science', 'scientist', 'mathematician', 'chemistry', 'biology', 'physics', 'nobel prize', 'invention', 'discovery', 'invented', 'discovered', 'science', 'Physicist', 'physicist', 'chemist', 'Chemist', 'Biologist', 'biologist']
politicianKeywords = ['Politician', 'Politics', 'Election', 'President', 'Vice-President', 'Vice President', 'Senate', 'Senator', 'Representative', 'Democracy', 'politician', 'politics', 'election', 'president', 'vice-president', 'vice president', 'senate', 'senator', 'representative', 'democracy']
#Declaring the first sentence (from the summary)
firstSentence = summary.split('.')[0]
profession = ['Scientist', 'Sportsperson', 'Politician']
professionFinal = ''
#Splitting the first sentence of the summary into separate words
firstSentenceList = firstSentence.split()
#Checking each word in the first sentence against the keywords in each profession to try to get a match
for i in firstSentenceList:
if i in sportspersonKeywords:
professionFinal = profession[1]
break
elif i in scientistKeywords:
professionFinal = profession[0]
break
elif i in politicianKeywords:
professionFinal = profession[2]
break
#if a match is found, then that person has that profession, if not, then their profession is not in our parameters
if professionFinal == '':
print('[PROFESSION]: NOT A SPORTPERSON, SCIENTIST, OR POLITICIAN')
else:
print('[PROFESSION]: ' + professionFinal)
Thanks guys!

Selecting dictionary nested in a list by index

Here is am example of the list:
{'Item': 'milk', 'Price': '2.0', 'Quantity': '2'}, {'Item': 'egg', 'Price': '12.0', 'Quantity': '1'}]
Here is my code:
def edit_items(info):
xy = info
print('Index | Orders')
for x in enumerate(xy):
print('\n')
print(x)
choice = int(input('Which entry would you like to edit? Choose by index. :'))
print(x[choice])
Id like the user to able to chose an entry by index, and allow them to edit information inside the dictionary.
So far my code prints out:
Index | Orders
(0, {'Item': 'milk', 'Price': '2.0', 'Quantity': '2'})
(1, {'Item': 'egg', 'Price': '12.0', 'Quantity': '1'})
But i have no idea how to choose one, assign It to a variable and carry out the ability to edit whats inside.
Cheers. Nalpak_
def edit_items(info):
xy = info
# to make multiple edits.
while True:
print('Index | Orders')
for x in range(len(xy)):
print(x,xy[x])
choice = int(input('Which entry would you like to edit?\nChoose by index: '))
print(xy[choice])
edit = input('What you want to edit: ') # Key val of dict
value = input("Enter: ") # Value for the specific key in dict
xy[choice][edit] = value
print('list updated.')
print(xy[choice])
more_edits = input('\nDo you want to make more edits?(y/n): ')
if more_edits == 'n':
break
edit_items(info)
this will help you make multiple edits.
If you want to edit an item in a dictionary, you can easily do it by accessing it by the key.
First, we set up the data
xy = [{'Item': 'milk', 'Price': '2.0', 'Quantity': '2'}, {'Item': 'egg', 'Price': '12.0', 'Quantity': '1'}]
Then if I understood you correctly, this edit_items method should do exactly what you need:
def edit_items(i):
name = input('Type in a new item name: ')
xy[i]['Item'] = name # 'Item' is the key.
Everything else is pretty much the same:
print('Index | Orders')
for x in enumerate(xy):
print('\n')
print(x)
choice = int(input('Which entry would you like to edit? Choose by index. :'))
print(xy[choice])
edit_items(choice)
print(xy)
If you want, you can also use input for getting a key (property) of an item you want to edit.

My search input functions works, but it only prints the last person's information in the list of dicts

I'm kind of new to python, and I need some help. I'm making an employee list menu. My list of dictionaries is:
person_infos = [ {'name': 'John Doe', 'age': '46', 'job position': 'Chair Builder', 'pay per hour': '14.96','date hired': '2/26/19'},
{'name': 'Phillip Waltertower', 'age': '19', 'job position': 'Sign Holder', 'pay per hour': '10','date hired': '5/9/19'},
{'name': 'Karen Johnson', 'age': '40', 'job position': 'Manager', 'pay per hour': '100','date hired': '9/10/01'},
{'name': 'Linda Bledsoe', 'age': '60', 'job position': 'CEO', 'pay per hour': '700', 'date hired': '8/24/99'},
{'name': 'Beto Aretz', 'age': '22', 'job position': 'Social Media Manager', 'pay per hour': '49','date hired': '2/18/12'}]
and my "search the list of dicts input function" is how the program is supposed to print the correct dictionary based on the name the user inputs:
def search_query(person_infos):
if answer == '3':
search_query = input('Who would you like to find: ')
they_are_found = False
location = None
for i, each_employee in enumerate(person_infos):
if each_employee['name'] == search_query:
they_are_found = True
location = i
if they_are_found:
print('Found: ', person_infos[location]['name'], person_infos[location]['job position'], person_infos[location]['date hired'], person_infos[location]['pay per hour'])
else:
print('Sorry, your search query is non-existent.')
and I also have this-
elif answer =='3':
person_infos = search_query(person_infos)
This seems like a step in the right direction, but for
search_query = input('Who would you like to find: ')
if I input of the names in person_infos, like "John Doe," it just prints the last dictionary's information (no matter which specific dictionary it is, the last one in the order will always be outputted) instead of John Doe's. in this case, it would only print "Beto Aretz's."
Can someone please help? It's something I've been struggling on for a while and it would be awesome.
I've researched so much and I could not find something with things that I either knew how to do, or were the input search.
Thanks,
LR
At first glance it looks like because your location=i is not indented inside your if statement so it is getting set to the latest i on each iteration of the for loop. Let me know if this helps.
def search_query(person_infos):
if answer == '3':
search_query = input('Who would you like to find: ')
they_are_found = False
location = None
for i, each_employee in enumerate(person_infos):
if each_employee['name'] == search_query:
they_are_found = True
location = i
if they_are_found:
print('Found: ', person_infos[location]['name'], person_infos[location]['job position'], person_infos[location]['date hired'], person_infos[location]['pay per hour'])
else:
print('Sorry, your search query is non-existent.')

Failing to append to dictionary. Python

I am experiencing a strange faulty behaviour, where a dictionary is only appended once and I can not add more key value pairs to it.
My code reads in a multi-line string and extracts substrings via split(), to be added to a dictionary. I make use of conditional statements. Strangely only the key:value pairs under the first conditional statement are added.
Therefore I can not complete the dictionary.
How can I solve this issue?
Minimal code:
#I hope the '\n' is sufficient or use '\r\n'
example = "Name: Bugs Bunny\nDOB: 01/04/1900\nAddress: 111 Jokes Drive, Hollywood Hills, CA 11111, United States"
def format(data):
dic = {}
for line in data.splitlines():
#print('Line:', line)
if ':' in line:
info = line.split(': ', 1)[1].rstrip() #does not work with files
#print('Info: ', info)
if ' Name:' in info: #middle name problems! /maiden name
dic['F_NAME'] = info.split(' ', 1)[0].rstrip()
dic['L_NAME'] = info.split(' ', 1)[1].rstrip()
elif 'DOB' in info: #overhang
dic['DD'] = info.split('/', 2)[0].rstrip()
dic['MM'] = info.split('/', 2)[1].rstrip()
dic['YY'] = info.split('/', 2)[2].rstrip()
elif 'Address' in info:
dic['STREET'] = info.split(', ', 2)[0].rstrip()
dic['CITY'] = info.split(', ', 2)[1].rstrip()
dic['ZIP'] = info.split(', ', 2)[2].rstrip()
return dic
if __name__ == '__main__':
x = format(example)
for v, k in x.iteritems():
print v, k
Your code doesn't work, at all. You split off the name before the colon and discard it, looking only at the value after the colon, stored in info. That value never contains the names you are looking for; Name, DOB and Address all are part of the line before the :.
Python lets you assign to multiple names at once; make use of this when splitting:
def format(data):
dic = {}
for line in data.splitlines():
if ':' not in line:
continue
name, _, value = line.partition(':')
name = name.strip()
if name == 'Name':
dic['F_NAME'], dic['L_NAME'] = value.split(None, 1) # strips whitespace for us
elif name == 'DOB':
dic['DD'], dic['MM'], dic['YY'] = (v.strip() for v in value.split('/', 2))
elif name == 'Address':
dic['STREET'], dic['CITY'], dic['ZIP'] = (v.strip() for v in value.split(', ', 2))
return dic
I used str.partition() here rather than limit str.split() to just one split; it is slightly faster that way.
For your sample input this produces:
>>> format(example)
{'CITY': 'Hollywood Hills', 'ZIP': 'CA 11111, United States', 'L_NAME': 'Bunny', 'F_NAME': 'Bugs', 'YY': '1900', 'MM': '04', 'STREET': '111 Jokes Drive', 'DD': '01'}
>>> from pprint import pprint
>>> pprint(format(example))
{'CITY': 'Hollywood Hills',
'DD': '01',
'F_NAME': 'Bugs',
'L_NAME': 'Bunny',
'MM': '04',
'STREET': '111 Jokes Drive',
'YY': '1900',
'ZIP': 'CA 11111, United States'}

Categories