I am trying to create a "This is Your New Name Generator" program. I am doing this by asking the user for their first and last name. The program then takes the first letter of their first name, and the last letter of the their last name, and pulls from two text files to give their new first and last name.
I've gotten as far as getting the user's first and last name, and pulling information from a file, however it always gives me the last line of the file.
I thought I could setup the files like dictionaries and then use the user's input as keys, but it doesn't seem to be working.
Any advice?
firstName = input("What is your first Name? ")
lastName = input("What is your last Name? ")
fN = firstName[0].lower()
lN_len = len(lastName) -1
lN = lastName[lN_len]
fNdict = {}
with open('firstName.txt') as f:
for line in f:
(fN, fNval) = line.split(",")
fNdict[fN] = fNval
lNdict = {}
with open('lastName.txt') as fileobj:
for line in fileobj:
lNkey, lNvalue = line.split(",")
lNdict[lN] = lNvalue
newFirstName = fNval
newLastName = lNvalue
print("Your zombie Name is: %s %s "%(newFirstName,newLastName))
Reference Image:
When you run these lines:
newFirstName = fNval
newLastName = lNvalue
fNval and lNvalue have the last values they had in their respective loops. I think you mean to use the user's first and last names as keys to the dictionaries, e.g.
newFirstName = fNdict[fN]
newLastName = lNdict[lN]
Note that this will fail if fN and lN aren't in the dictionaries. You might want to create defaultdicts instead.
Note also that Python has an official style guide that most Python developers follow. Please consider reading it and writing your code accordingly. The code you've shared is very hard to read.
You could follow a slightly different implementation to achieve the same result.
Create two python dictionaries with all the associations letters - first names and letter - last names.
Write them in a file using json. This file will substitute yours firstName.txt and lastName.txt
This should be done only once to create the file with the names.
Then your name generator is a script which:
Loads those two dictionaries.
Ask the user for an input to obtain the keys.
Retrieve the names from the dictionaries using the user input.
The first two points are implemented in this way:
import json
#these are just brief examples, provide complete dictionaries.
firstnames = {"A": "Crafty", "B": "Brainy"}
lastnames = {"A": "Decapitator", "B": "McBrains"}
with open("fullnames.txt", "w") as ff:
json.dump(firstnames, ff)
ff.write('\n')
json.dump(lastnames, ff)
This would be a script to generate the file with the names.
The name generator would be:
import json
with open("fullnames.txt", "r") as ff:
ll = ff.readlines()
firstnames = json.loads(ll[0].strip())
lastnames = json.loads(ll[1].strip())
inputfirst = input("What is your first Name? ")
inputlast = input("What is your last Name? ")
fn = inputfirst[0].upper()
ln = inputlast[-1].upper() #negative indexes start from the last element of the iterable, so -1 would be the last.
print("Your zombie Name is: {} {} ".format(firstnames[fn], lastnames[ln])) #using string format method, better that the old %
Related
I am a newbie. I failed one of the test cases in a phone book problem. As per the question, a user is expected to enter a single line input which contains a name (which can be one or more words) followed by a number. I have to split the the input into ["name","number"] and store it in dictionary. Note that the name will have one or more words(Eg: John Conor Jr. or Apollo Creed). I am confused with the splitting part. I tried out the split() function and re.split(). Not sure I can solve this.
Sample input 1 : david james 93930000
Sample Input 2 : hshhs kskssk sshs 99383000
Output: num = {"david james" : "93930000", "hshhs kskssk sshs" : "99383000"}
I need to store it in a dictionary where the key:value is "david james": "93930000"
Please help. Thank you
=====>I found a solution<==========
if __name__ == '__main__':
N=int(input())
phonebook={}
(*name,num) = input().split()
name = ''.join(map(str,name)
phonebook.update({name:num})
print(phonebook)
The astrik method words. But for a large data set this might slow me down. Not sure.
So im assuming that the inputs stated are coming from a user, if that
is the case you could change the format in your code to something
similar to this. You can change the range depending on how many inputs you want.
name = {}
for i in range(5):
student_name = input("Enter student's name: ")
student_mark = input("Enter student's mark: ")
name[student_name.title()] = student_mark
print(marks)
This should print the results in the way you mentioned!
Please check for the updated answer if this is what you are looking
for.
# Sample text in a line...
# With a name surname and number
txt = "Tamer Jar 9000"
# We define a dictionary variable
name_dictionary = {}
# We make a list inorder to appened the name and surname to the list
name_with_surname = []
# We split the text and if we print it out it should look something like this
# "Tamer", "Jar", "9000"
# But you need the name and surname together so we do that below
x = txt.split()
# We take the first value of the split text which is "Tamer"
# And we take the second value of the split text us "Jar"
name = x[0]
surname = x[1]
# And here we append them to our list
name_with_surname.append(name + " " + surname)
#print(name_with_surname)
# Finally here to display the values in a dictionary format
# We take the value of the list which is "Tamer Jar" and the value of the number "9000"
name_dictionary[name_with_surname[0]] = x[2]
print(name_dictionary)
The above answers can't handle if a data has too many name parts in one line.
Try my code below.
You can just loop through whatever the total number of inputs you want.
phonebook = {}
total_inputs = int(input())
for i in range(total_inputs):
name_marks = input().split() # taking input and splitting them by spaces
name = " ".join(x for x in name_marks[:-1]) # extracting the name
marks = name_marks[-1] # extracting the marks
phonebook[name] = marks # storing the marks in the dictionary
This way you can store the marks for the name. It will handle even one input has many name parts.
Looking to have my code read one text file and store the line number of a user input as num and then use the variable num to read the same line on another file.
currently, the code for the first step of reading the first text file is working and has been tested but the second part doesn't display anything after being executed. I have changed multiple things but am still stuck. Help would be much appreciated.
here is my code:
print("Check Stock")
ca = input("Check all barcodes?")
if ca == "y":
for x in range(0,5):
with open ("stockbarcodes.txt") as f:
linesa = f.readlines()
print(linesa[x])
with open ("stockname.txt") as f:
linesb = f.readlines()
print(linesb[x])
print(" ")
else:
bc = input("Scan barcode: ")
f1 = open ("stockname.txt")
for num, line in enumerate(f1, 1):
if bc in line:
linesba = f1.readlines()
print(linesba[num])
As user Ikriemer points, it seems that you want to retrieve the stock name based on the barcode. For that kind of task you rather create a normalized Data Base, which discribes Entities, Properties and relationships. As you can se here there are a lot of things to take into account.
This code was tested on Mac OS, but considering OP's comment (who seems to be using windows), it is ok if the dtype is not specified.
Considering that the above solution may not be as quick as you like, you also have two options.
First option
As I can not check the content of your example files, the strategy that you show in your code makes me believe that your assuming both files are ordered, in a way that first line of the barcode file corresponds to first item in the stock name file. Given that, you can query the index of an element (barcode) in an array like data structure, and retrieve the element of another array (name) stored in the same position. Code below:
import numpy as np
print("Check Stock")
ca = input("Check all barcodes? (y/n): ")
if ca == "y":
for x in range(0, 5):
with open("stockbarcodes.txt") as f:
linesa = f.readlines()
print(linesa[x], sep="")
with open("stockname.txt") as f:
linesb = f.readlines()
print(linesb[x], sep="")
print(" ")
else:
try:
codes = np.genfromtxt("stockbarcodes.txt").tolist()
names = np.genfromtxt("stockname.txt", dtype=np.str).tolist()
bc = input("Scan barcode: ")
index = codes.index(int(bc))
print(names[index])
except IndexError:
print("Bar code {} not found".format(bc))
Second option
This option could be considered a workaround method to a data base like file. You need to store your data in some way that you can search the values associated with an specific entry. Such kind of tasks could be done with a dictionary. Just replace the else clause with this:
else:
try:
codes = np.genfromtxt("stockbarcodes.txt").tolist()
names = np.genfromtxt("stockname.txt", dtype=np.str).tolist()
table = {k: v for k, v in zip(codes, names)}
bc = input("Scan barcode: ")
print(table[int(bc)])
except KeyError:
print("Bar code {} not found".format(bc))
Again, in the dictionary comprehension we are assuming both files are ordered. I strongly suggest you to validate this assumption, to warranty that the first bar code corresponds to the first stock, second to second, and so on. Only after that, you may like to store the dictionary as a file, so you can load it and query it as you please. Check this answer fot that purpose.
I have written code that creates a text file (if it doesn't exist) and asks you to input a name and an age to record peoples names and ages. I would like to add an elif into my code so that I can update peoples ages.
For example if a text file held the name Paul and their age was 46 and I typed in Paul when asked to input a name, I'd like it to just ask for an updated age.
Here is my attempt that simply doesn't work.
Code:
while True:
family=open("FamilyAges.txt",'a+')
familyR=open("FamilyAges.txt",'r')
line1= familyR.readlines(1)
name = input('Enter name of person : ')
if name == 'end':
break
elif name == line1:
print('test')
else:
age = input('Enter age of person : ')
family.write((name)+' '+(age)+'\n')
family.close()
Text File:
Paul 46
Sarah 46
The best solution is to read all the file, keep it in memory using a dict then update the dict every time you add a name.
When you decide to stop (input 'end') overwrite the file with the new values in the dict
The following solves your immediate problem with the code you posted, however for the goal you described you should think about: This code only checks the first line of your file but you want to check if the name is anywhere in the file.
readlines(1) returns a list with one element (the first line). So what you need is:
while True:
family=open("FamilyAges.txt",'a+')
familyR=open("FamilyAges.txt",'r')
line1= familyR.readlines(1)
name = input('Enter name of person : ')
if name == 'end':
break
elif name in line1[0]:
print('test')
else:
age = input('Enter age of person : ')
family.write((name)+' '+(age)+'\n')
family.close()
Note the line1[0] and the name in line1[0] (you need this because your line contains not only the name but additional text).
A bit longer then Joe's solution, but I like functions more. I did not correct your code, because certain parts were missing - rewriting seemed a better option keeping to stuff you did use.
After gianluca answer "what" to do I implemented an example of that for you.
I use the with open(...) as f: instead of your type of file reading as it automatically will close/flush/dispose of the filehandle when leaving the following block. Its the recommed way to operate with files. Dictionariesis a data structure for fast key/value access and better suited to your problem then simple strings.
See also reading-and-writing-files
Reading the whole file
input loop until done, modifying the dict
then (if needed) saving it.
Breaking up funcionality into funcitons is that have a limited scope and are easier to understand helps keep the code cleaner.
def readFile(fn):
"""Read the file given as by filename fn.
Expected format:
one key:value per line, key being a name, value a string as age.
Returns a dictionary of the parsed contents key:value if no
errors occure. Returs False on IOError or FileNotFoundError"""
try:
with open(fn,"r") as f:
lines = f.read().split("\n") # read all, split at linebreaks
print(lines) # debugging output
rv = {}
for l in lines: # parse all lines
item =l.split(":",2) # split each
if item is not None and len(item)==2: # must be 2 parts
rv[item[0]] = item[1] # put key/valu into dict
return rv # return dict
except IOError:
return False # error - return false
except FileNotFoundError:
pass # error - no file, thats ok
return {} # no file found, return empty dict
def saveFile(fn,famil):
"""Saves a dictionary famil as filename fn.
Produced format:
one key:value per line, key being a name, value a string as age.
Overwrites existing file of same name with new contents."""
with open(fn,"w+") as f:
for i in famil: # for all keys in dict
f.write(i + ":" + famil[i] + "\n") # write file
fileName = "FamilyAges.txt" # consistent filename
family = readFile(fileName) # read it
if not isinstance(family,dict): # check if no error, if error, print msg & quit
print("Error reading file")
else: # we got a dict
print(family) # print it
gotInput = False # remember for later if we need to save new data
while True: # loop until name input is "end"
name = input('Enter name of person : ') # input name
if name == 'end': # check break condition
break
else:
age = input('Enter age of person : ') # input age as string, no validation
family[name] = age # store in dictionary
gotInput = True # this will "alter" existing
# ages for existing names
if (gotInput): # if input happened, save data to file
saveFile(fileName, family)
print(family) # print dict before end
The steps:
if the file exists (could use try...except or os.path):
Create a dictionary of name: age pairs of people already in there
else:
Create an empty dictionary
begin a loop
input name
if name == "end" break out of loop
input age
set name entry in the dictionary to age (will override if not already set)
continue looping
open the file again, but in write ("w") mode so it is blanked
loop through each person in the dictionary (old and new)
write to the file their name and age (separated by a space) and then a new-line
Here's what that looks like:
try:
d = {n:a for n, a in (l.split() for l in open("FamilyAges.txt").readlines())}
except FileNotFoundError:
d = {}
while True:
name = input("name: ")
if name == "end":
break #will escape loop here, so no need for `elif`s
age = input("age: ") #no need to convert to an integer as noo calculations
d[name] = age
with open("FamilyAges.txt", "w") as f:
for person in d.items():
f.write(" ".join(person) + "\n")
And it works!
$ python t.py
name: bob
age: 23
name: cat
age: 98
name: end
$ cat FamilyAges.txt
bob 23
cat 98
$ python t.py
name: bob
age: 67
name: fish
age: 10
name: end
$ cat FamilyAges.txt
bob 67
cat 98
fish 10
I have a task where I need to record peoples scores in a text file. My Idea was to set it out like this:
Jon: 4, 1, 3
Simon: 1, 3, 6
This has the name they inputted along with their 3 last scores (Only 3 should be recorded).
Now for my question; Can anyone point me in the right direction to do this? Im not asking for you to write my code for me, Im simply asking for some tips.
Thanks.
Edit: Im guessing it would look something like this: I dont know how I'd add scores after their first though like above.
def File():
score = str(Name) + ": " + str(correct)
File = open('Test.txt', 'w+')
File.write(score)
File.close()
Name = input("Name: ")
correct = input("Number: ")
File()
You could use pandas to_csv() function and store your data in a dictionary. It will be much easier than creating your own format.
from pandas import DataFrame, read_csv
import pandas as pd
def tfile(names):
df = DataFrame(data = names, columns = names.keys())
with open('directory','w') as f:
f.write(df.to_string(index=False, header=True))
names = {}
for i in xrange(num_people):
name = input('Name: ')
if name not in names:
names[name] = []
for j in xrange(3):
score = input('Score: ')
names[name].append(score)
tfile(names)
Simon Jon
1 4
3 1
6 3
This should meet your text requirement now. It converts it to a string and then writes the string to the .txt file. If you need to read it back in you can use pandas read_table(). Here's a link if you want to read about it.
Since you are not asking for the exact code, here is an idea and some pointers
Collect the last three scores per person in a list variable called last_three
do something like:
",".join(last_three) #this gives you the format 4,1,3 etc
write to file an entry such as
name + ":" + ",".join(last_three)
You'll need to do this for each "line" you process
I'd recommend using with clause to open the file in write mode and process your data (as opposed to just an "open" clause) since with handles try/except/finally problems of opening/closing file handles...So...
with open(my_file_path, "w") as f:
for x in my_formatted_data:
#assuming x is a list of two elements name and last_three elems (example: [Harry, [1,4,5]])
name, last_three = x
f.write(name + ":" + ",".join(last_three))
f.write("\n")# a new line
In this way you don't really need to open/close file as with clause takes care of it for you
I am trying to get a list of presidents alphabetized by last name, even though the file that it is being drawn is currently listed first name, last name, date in office, and date out of office.
Here is what I have, any help on what I need to do with this. I have searched around for some answers, and most of them are beyond my level of understanding. I feel like I am missing something small. I tried to break them all out into a list, and then sort them, but I could not get it to work, so this is where I started from.
INPUT_FILE = 'presidents.txt'
OUTPUT_FILE = 'president_NEW.txt'
OUTPUT_FILE2 = 'president_NEW2.txt'
def main():
infile = open(INPUT_FILE)
outfile = open(OUTPUT_FILE, 'w')
outfile2 = open(OUTPUT_FILE2,'w')
stuff = infile.readline()
while stuff:
stuff = stuff.rstrip()
data = stuff.split('\t')
president_First = data[1]
president_Last = data[0]
start_date = data[2]
end_date = data[3]
sentence = '%s %s was president from %s to %s' % \
(president_First,president_Last,start_date,end_date)
sentence2 = '%s %s was president from %s to %s' % \
(president_Last,president_First,start_date, end_date)
outfile2.write(sentence2+ '\n')
outfile.write(sentence + '\n')
stuff = infile.readline()
infile.close()
outfile.close()
main()
What you should do is put the presidents in a list, sort that list, and then print out the resulting list.
Before your for loop add:
presidents = []
Have this code inside the for loop after you pull out the names/dates
president = (last_name, first_name, start_date, end_date)
presidents.append(president)
After the for loop
presidents.sort() # because we put last_name first above
# it will sort by last_name
Then print it out:
for president in presidents
last_name, first_name, start_date, end_date = president
string1 = "..."
It sounds like you tried to break them out into a list. If you had trouble with that, show us the code that resulting from that attempt. It was right way to approach the problem.
Other comments:
Just a couple of points where you code could be simpler. Feel free to ignore or use this as you want:
president_First=data[1]
president_Last= data[0]
start_date=data[2]
end_date=data[3]
can be written as:
president_Last, president_First, start_date, end_date = data
stuff=infile.readline()
And
while stuff:
stuff=stuff.rstrip()
data=stuff.split('\t')
...
stuff = infile.readline()
can be written as:
for stuff in infile:
...
#!/usr/bin/env python
# this sounds like a homework problem, but ...
from __future__ import with_statement # not necessary on newer versions
def main():
# input
with open('presidents.txt', 'r') as fi:
# read and parse
presidents = [[x.strip() for x in line.split(',')] for line in fi]
# sort
presidents = sorted(presidents, cmp=lambda x, y: cmp(x[1], y[1]))
# output
with open('presidents_out.txt', 'w') as fo:
for pres in presidents:
print >> fo, "president %s %s was president %s %s" % tuple(pres)
if __name__ == '__main__':
main()
I tried to break them all out into a list, and then sort them
What do you mean by "them"?
Breaking up the line into a list of items is a good start: that means you treat the data as a set of values (one of which is the last name) rather than just a string. However, just sorting that list is no use; Python will take the 4 strings from the line (the first name, last name etc.) and put them in order.
What you want to do is have a list of those lists, and sort it by last name.
Python's lists provide a sort method that sorts them. When you apply it to the list of president-info-lists, it will sort those. But the default sorting for lists will compare them item-wise (first item first, then second item if the first items were equal, etc.). You want to compare by last name, which is the second element in your sublists. (That is, element 1; remember, we start counting list elements from 0.)
Fortunately, it is easy to give Python more specific instructions for sorting. We can pass the sort function a key argument, which is a function that "translates" the items into the value we want to sort them by. Yes, in Python everything is an object - including functions - so there is no problem passing a function as a parameter. So, we want to sort "by last name", so we would pass a function that accepts a president-info-list and returns the last name (i.e., element [1]).
Fortunately, this is Python, and "batteries are included"; we don't even have to write that function ourself. We are given a magical tool that creates functions that return the nth element of a sequence (which is what we want here). It's called itemgetter (because it makes a function that gets the nth item of a sequence - "item" is more usual Python terminology; "element" is a more general CS term), and it lives in the operator module.
By the way, there are also much neater ways to handle the file opening/closing, and we don't need to write an explicit loop to handle reading the file - we can iterate directly over the file (for line in file: gives us the lines of the file in turn, one each time through the loop), and that means we can just use a list comprehension (look them up).
import operator
def main():
# We'll set up 'infile' to refer to the opened input file, making sure it is automatically
# closed once we're done with it. We do that with a 'with' block; we're "done with the file"
# at the end of the block.
with open(INPUT_FILE) as infile:
# We want the splitted, rstripped line for each line in the infile, which is spelled:
data = [line.rstrip().split('\t') for line in infile]
# Now we re-arrange that data. We want to sort the data, using an item-getter for
# item 1 (the last name) as the sort-key. That is spelled:
data.sort(key=operator.itemgetter(1))
with open(OUTPUT_FILE) as outfile:
# Let's say we want to write the formatted string for each line in the data.
# Now we're taking action instead of calculating a result, so we don't want
# a list comprehension any more - so we iterate over the items of the sorted data:
for item in data:
# The item already contains all the values we want to interpolate into the string,
# in the right order; so we can pass it directly as our set of values to interpolate:
outfile.write('%s %s was president from %s to %s' % item)
I did get this working with Karls help above, although I did have to edit the code to get it to work for me, due to some errors I was getting. I eliminated those and ended up with this.
import operator
INPUT_FILE = 'presidents.txt'
OUTPUT_FILE2= 'president_NEW2.txt'
def main():
with open(INPUT_FILE) as infile:
data = [line.rstrip().split('\t') for line in infile]
data.sort(key=operator.itemgetter(0))
outfile=open(OUTPUT_FILE2,'w')
for item in data:
last=item[0]
first=item[1]
start=item[2]
end=item[3]
outfile.write('%s %s was president from %s to %s\n' % (last,first,start,end))
main()