I'm a beginner in Python.
I have a simple dictionary called G8_Leaders.txt - as follows: {Cameron:UK, Merkel:Germany, Obama:USA, Putin:Russia}
and I'm trying to iterate through the pairs - display the contents in a column, using a basic "for" loop like so:
f0 = "G8_Leaders.txt"
f1 = open(f0)
for i in f1:
print(i, end=" ")
else:
print("Finished with Document: ", f0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I'd like the results in a column, such as:
Merkel Germany
Cameron UK
Obama USA
and so on...However, the results are only printed in one line, as they are displayed in the text file.
What is the proper way to do this?
First, you have to fix the representation of your dictionary in your file to be as:
d = {'Cameron':'UK', 'Merkel':'Germany', 'Obama':'USA', 'Putin':'Russia'}
It can be done programmatically by invoking str() on each key and value of d.
Assuming that that is fixed, one solution would be:
# Create a file for test bench:
d = {'Cameron':'UK', 'Merkel':'Germany', 'Obama':'USA', 'Putin':'Russia'}
with open("G8_Leaders.txt", "w") as f:
f.write(str(d) +'\n')
#Read and print from the file:
with open("G8_Leaders.txt", "r") as f:
data = f.readlines()
for line in data:
d = eval(line)
for y, z in d.items():
print(y, z)
Output:
Cameron UK
Merkel Germany
Putin Russia
Obama USA
Ok, a couple things are going on here. f1 is a file object, which is not what you are expecting. If you want to access it as a string, you would do
`f1_string = f1.read()`
Which reads the file into the variable f1_string as a string. You could do:
for line in f1.readlines():
# operate on one line at a time in this block
if you would prefer to read a line at a time, which will work in your case if each element is on its own line in the text file. Since we don't know what exactly what your text file looks like, it's hard to give more specific help. The json module people are referring to can be found here, but I'm not entirely sure that's what you want.
Assuming that your text file is just as you've described it, then try the following:
with open(f0, 'r') as f:
for line in f:
items = line.split(',')
for item in items:
leader = item.split(':')[0].replace('{','')
country = item.split(':')[1].replace('}','')
print(leader,country)
This should work regardless of whether or not your data has line breaks in it.
Try this to iterate through a dictionary:
leaders = {'Cameron':'UK', 'Merkel':'Germany', 'Obama':'USA', 'Putin':'Russia'}
for leader in leaders:
print(leader, leaders[leader])
import json
print("\n".join(x+" "+ y for x,y in json.load(open("fname.txt" ,"rb")).iteritems()))
just load it as json(at least I think its not entirely clear if you have properly formatted json in your text file ) ... (warning though dictionaries are unordered so if you need a certain order you will have to provide more clarification)
Related
The title of my question might be a bit confusing - maybe that's because I am a little confused myself.
I have a task to create a small billing system for a restaurant (It is not a real restaurant).
I have 3 text files. The first one being the menu.txt. In the file, each line consists of the name of a dish and its price, seperated by a comma. Then I have 2 order files order1.txt and order2.txt Each line contains an item from the menu that has been ordered.
My own suggestion to this task was to put the menu file into a list and then make it a dictionary.
This is my solution:
def compute_total(mfile, ofile):
dictionary = {}
newlist = []
with open('menu.txt') as f:
for line in f:
line = line.replace(',', '')
newlist.append(line.split())
for strings in newlist:
dictionary[strings[0]] = strings[1]
I feel like I am on the right way with this but I don't really know how make code from here.
Because I know that I want to somehow see if for example: order1 is in the dictionary (menu) and then calculate the values (prices) of the dishes.
I was thinking maybe something like this below, but it does not work and I am stuck.
for k, v in dictionary.items():
if int(k) in dictionary.items():
Dvalues.append(v)
I hope you can give me some advice to get going. I am a novice so I really hope you would take some time to help me with small problem (for you) like this.
Best regards,
SEE
Python's csv package is great for dealing with comma separated files. Instead of having to parse each line manually, the csv module will be able to convert each line to a list of values that were previously separated by commas. Then, you can just use parallel assignment to get the items and prices for each line, and store them in the dictionary:
with open('menu.txt') as f:
for line in f:
item, price = csv.reader(line, quotechar="'", delimiter=",")
dictionary[item] = price
Now that you've stored all the menu items in the dictionary, all you have to do is read each item line from the other text files, pass that item to your dictionary, get back the price, and add it to the sum:
order1_total = 0
with open(mfile) as f:
for line in f:
item = line
order1_total += dictionary[item]
Don't forget to add the line import csv to the top of your program. Hope it helps! Good luck!
So I'm creating a program which should be able to read 8 separate text files and gather the information from those files into a single files.
First file contains information about the atheletes like this:
number;name;division.
The other files contain results from individual sport events like this:
number;result.
The program should be able to gather all the information about the athletes and put into a single file like this:
number;name;division;event1;event2...;event7.
The number is atheletes participant number and all other information should be "linked" to that number.
I'm really confused whether to use dict or list or both to handle and store the information from the text files.
The program is a lot more complex than explained above but I can work out the details myself. Also the allowed import libraries are math, random and time. I know these are pretty vague instructions but like I said I don't need a complete, functional program but rather guidelines how to get started. Thanks!
Consult this post for how to read a file line-by-line.
with open(...) as f:
for line in f:
<do something with line>
Consult this post on how to split each line of a CSV.
Consult this post about how to add to a dictionary. I suggest adding a tuple as each entry in the dictionary.
d['mynewkey'] = 'mynewvalue'
Then concatenate and reassign the tuples to add data from new files:
d['mynewkey']=d['mynewkey'] + (newval1, newval2, newval3)
And remember, it is the commas that make a tuple, not the parentheses.
That should get you started.
first of all
open csv file for writing, next open all of your text files.
To do this use python with statement. You can easily open all text files in one line :)
with open('result.csv', 'w') as csvfile:
# write column headers
csvfile.write('number;name;division;event1; ...')
with open('file1.txt', 'r') as f1, open('file2.txt' , 'r') as f2, open(...) as f:
f1_line = f1.readline()
f2_line = f2.readline()
# rest of your login ....
csvfile.write(';'.join(item for item in [number, name, division, event1, ...]) + '.\n')
when You open all files, read from them line by line. Collect lines from all files, extract from line what you need and write it to csv file :)
PS. I don't know how many lines your files will have, but loading everything to memory (list or dict whatever) isn't good idea....
You can use a dict with the athelete numbers as keys to identify them, and use a class to store all other information in a meaningful and nice way. The results can be added to a list of an athlete object, and the athlete object be identified by the number (which is the dict key).
Sample input athletes.csv:
1;Jordan;Basketball.
2;Michael;Soccer.
3;Ariell;Swimming.
Sample input athletes_events.csv:
2;23.5.
2;25.7.
3;174.5.
1;13.
1;15.
2;21.3.
3;159.9.
2;28.6
1;19.
Code:
class Athlete:
def __init__(self, name, division):
self.name = name
self.division = division
self.events = []
athletes = {}
with open("athletes.csv") as file:
for line in file:
number, name, division = line.strip(".\n").split(";")
# could cast number to int, but we don't have to
athletes[number] = Athlete(name, division)
with open("athletes_events.csv") as file:
for line in file:
number, result = line.strip("\n").split(";")
result = float(result.rstrip("."))
try:
athletes[number].events.append(result)
except KeyError:
print("There's no athlete with number %s" % number)
for number, athlete in sorted(athletes.items()):
print("%s - %s (%s):" % (athlete.name, athlete.division, number))
for i, result in enumerate(athlete.events, 1):
print(" Event %i = %s" % (i, result))
print()
Result:
Jordan - Basketball (1):
Event 1 = 13.0
Event 2 = 15.0
Event 3 = 19.0
Michael - Soccer (2):
Event 1 = 23.5
Event 2 = 25.7
Event 3 = 21.3
Event 4 = 28.0
Ariell - Swimming (3):
Event 1 = 174.5
Event 2 = 159.9
Just replace the print()s by some file writing operation.
At the moment I have a text file with people who swim and their times, such as this,
jack 12
sarah 20
ben 4
Now i would like to be able to search this for say sarah and for it to return the code.
This is what i currently have.
def Timers(swimmer):
myFile = open("race.txt","r")
lists = []
for eachLine in myFile:
lists += [eachLine.rstrip("\n")]
so I compiled all them into a single list, although i know i can check the list to see if they are there although i cannot work out how i would just select the time.
At this point i know if i get say, sarah 12 I can then use split and then just formate it to get the times.
Thank you for the help.
You want a dict, a python mapping instead, and read the file only once:
def Timers():
with open("race.txt","r") as myFile:
swimmers = {}
for eachLine in myFile:
if line.strip():
swimmer, timer = line.split()
swimmers[swimmer] = timer
return swimmers
The .split() call splits the line on whitespace, giving you a name and a timer string for each line.
Now Timers() returns a mapping containing all swimmer names as the keys, and their times as values. You can simply look up each and every swimmer:
timers = Timers()
print timers['sarah']
Another approach to the problem:
def Timer(swimmer):
myFile = open("race.txt", "r")
lists = myFile.readlines()
found = [l for l in lists if l.startswith(swimmer)][0] # Gets first found swimmer
time = found.split()[-1] # Gets last item (eg. time) in splitted list
myFile.close()
return time
print Timer('jack')
This works even if the swimmer is specified with both first and last name. I used the same way to open the file as you did. But you really should use the with-statement as in the previous answer!
I'm teaching myself python and wanted to learn how to search through text files. For example, i've got a long list of full names and addresses, and want to be able to type in a first name and then print the details corresponding to that name. What would be the best way to go about this? Thanks!
The data I have is in a .txt file in columns like this:
Doe, John London
Doe, Jane Paris
If you've designed the data format, fixed-width columns aren't a very good one. But if you're stuck with them, they're easy to deal with.
First, you want to parse your data:
addressbook = []
with open('addressbook.txt', 'r') as f:
for line in f:
name, city = line[:17], line[17:]
last, first = name.split(',')
addressbook.append((first, last, city))
But now, you want to be able to search by first name. You can do that, but it might be slow for a huge addressbook, and the code won't be very direct:
def printDetails(addressbook, firstname):
for (first, last, city) in addressbook:
if first == firstname:
print fist, last, city
What if, instead of just a list of tuples, we used a dictionary, mapping first names to the other field?
addressbook = {}
with open('addressbook.txt', 'r') as f:
for line in f:
name, city = line[:17], line[17:]
last, first = name.split(',')
addressbook[first]=((last, city))
But that's no good—each new "John" will erase any previous "John". So what we really want is a dictionary, mapping first names to lists of tuples:
addressbook = collections.defaultdict(list)
with open('addressbook.txt', 'r') as f:
for line in f:
name, city = line[:17], line[17:]
last, first = name.split(',')
addressbook[first].append((last, city))
Now, if I want to see the details for that first name:
def printDetails(addressbook, firstname):
for (last, city) in addressbook[firstname]:
print firstname, last, city
Whichever way you go, there are a few obvious places to improve this. For example, you may notice that some of the fields have extra spaces at the start or end. How would you get rid of those? If you call printDetails on "Joe" and there is no "Joe", you get nothing at all; maybe a nice error message would be better. But once you've got the basics working, you can always add more later.
I would make judicious use of the split command. It depends on how your file is delimited, of course, but your example shows that the characters splitting the data fields are spaces.
For each line in the file, do something like this:
last, first, city = [data.strip(',') for data in line.split(' ') if data]
And then run your comparison based on those attributes.
Obviously, this will break if your data fields have spaces in them, so ensure that's not the case before you take a simple approach like this.
To read a text-file in python, you do something like this:
f = open('yourtextfile.txt')
for line in f:
//The for-loop will loop thru the whole file line by line
//Now you can do what you want to the line, in your example
//You want to extract the first and last name and the city
You could do something as simple as this:
name = raw_input('Type in a first name: ') # name to search for
with open('x.txt', 'r') as f: # 'r' means we only intend to read
for s in f:
if s.split()[1] == name: # s.split()[1] will return the first name
print s
break # end the loop once we've found a match
else:
print 'Name not found.' # this will be executed if no match is found
Type in a first name: Jane
Doe, Jane Paris
Relevant documentation
Reading and Writing Files
open
Write a program which reads a text
file called input.txt which contains
an arbitrary number of lines of the
form ", " then records this
information using a dictionary, and
finally outputs to the screen a list
of countries represented in the file
and the number of cities contained.
For example, if input.txt contained the following:
New York, US
Angers, France
Los Angeles, US
Pau, France
Dunkerque, France
Mecca, Saudi Arabia
The program would output the following (in some order):
Saudi Arabia : 1
US : 2
France : 3
My code:
from os import dirname
def parseFile(filename, envin, envout = {}):
exec "from sys import path" in envin
exec "path.append(\"" + dirname(filename) + "\")" in envin
envin.pop("path")
lines = open(filename, 'r').read()
exec lines in envin
returndict = {}
for key in envout:
returndict[key] = envin[key]
return returndict
I get a Syntax error: invalid syntax... when I use my file name
i used file name input.txt
I don't understand what you are trying to do, so I can't really explain how to fix it. In particular, why are you execing the lines of the file? And why write exec "foo" instead of just foo? I think you should go back to a basic Python tutorial...
Anyway, what you need to do is:
open the file using its full path
for line in file: process the line and store it in a dictionary
return the dictionary
That's it, no exec involved.
Yup, that's a whole lot of crap you either don't need or shouldn't do. Here's how I'd do it prior to Python 2.7 (after that, use collections.Counter as shown in the other answers). Mind you, this'll return the dictionary containing the counts, not print it, you'd have to do that externally. I'd also not prefer to give a complete solution for homeworks, but it's already been done, so I suppose there's no real damage in explaining a bit about it.
def parseFile(filename):
with open(filename, 'r') as fh:
lines = fh.readlines()
d={}
for country in [line.split(',')[1].strip() for line in lines]:
d[country] = d.get(country,0) + 1
return d
Lets break that down a bit, shall we?
with open(filename, 'r') as fh:
lines = fh.readlines()
This is how you'd normally open a text file for reading. It will raise an IOError exception if the file doesn't exist or you don't have permissions or the likes, so you'll want to catch that. readlines() reads the entire file and splits it into lines, each line becomes an element in a list.
d={}
This simply initializes an empty dictionary
for country in [line.split(',')[1].strip() for line in lines]:
Here is where the fun starts. The bracket enclosed part to the right is called a list comprehension, and it basically generates a list for you. What it pretty much says, in plain english, is "for each element 'line' in the list 'lines', take that element/line, split it on each comma, take the second element (index 1) of the list you get from the split, strip off any whitespace from it, and use the result as an element in the new list"
Then, the left part of it just iterates over the generated list, giving the name 'country' to the current element in the scope of the loop body.
d[country] = d.get(country,0) + 1
Ok, ponder for a second what would happen if instead of the above line, we'd used the following:
d[country] = d[country] + 1
It'd crash, right (KeyError exception), because d[country] doesn't have a value the first time around.
So we use the get() method, all dictionaries have it. Here's the nifty part - get() takes an optional second argument, which is what we want to get from it if the element we're looking for doesn't exist. So instead of crashing, it returns 0, which (unlike None) we can add 1 to, and update the dictionary with the new count. Then we just return the lot of it.
Hope it helps.
I would use a defaultdict plus a list to mantain the structure of the information.
So additional statistics can be derived.
import collections
def parse_cities(filepath):
countries_cities_map = collections.defaultdict(list)
with open(filepath) as fd:
for line in fd:
values = line.strip().split(',')
if len(values) == 2:
city, country = values
countries_cities_map[country].append(city)
return countries_cities_map
def format_cities_per_country(countries_cities_map):
for country, cities in countries_cities_map.iteritems():
print " {ncities} Cities found in {country} country".format(country=country, ncities = len(cities))
if __name__ == '__main__':
import sys
filepath = sys.argv[1]
format_cities_per_country(parse_cities(filepath))
import collections
def readFile(fname):
with open(fname) as inf:
return [tuple(s.strip() for s in line.split(",")) for line in inf]
def countCountries(city_list):
return collections.Counter(country for city,country in city_list)
def main():
cities = readFile("input.txt")
countries = countCountries(cities)
print("{0} cities found in {1} countries:".format(len(cities), len(countries)))
for country, num in countries.iteritems():
print("{country}: {num}".format(country=country, num=num))
if __name__=="__main__":
main()