Replacing data in files with new inputs - python

First of all my program must work with several files and 10 inputs in every file, this is just little piece, to be clear.
My code right now:
code = input(">> ")
print("\nPress <Enter> and parameter will be same!")
f = open("komad_namestaja.txt", "r")
allDATA = f.readlines()
f.close()
for line in allDATA:
lst = line.split("|")
if code == lst[0]:
print("\nName :", lst[1])
name = input("New Name >> ")
if name == "":
name = lst[1]
f = open("komad_namestaja.txt", "r")
allDATA = f.read()
f.close()
newdata = allDATA.replace(lst[1], name)
f = open("komad_namestaja.txt", "w")
f.write(newdata)
f.close()
print("\ndestination :", lst[2])
destination = input("New destination >> ")
if destination == "":
destination = lst[2]
#Writting function here
File before:
312|chessburger|Denmark
621|chesscake|USA
code input: 312
name input: Gyros
destination input: Poland
file after inputs:
312|Gyros|Poland
621|chesscake|USA
Problem is this replacing in file I cant write 7 lines code every time, because I have 10 x 5 inputs, and also I tried everything and cant make function of this.
I must write some function for reading/writing/replacing or replacing all inputs after last one.

You don't have to read the file in every time to modify one field, write it out, reopen it to change another field, and so on. That's inefficient, and in your case, causes code explosion.
Since your files are small, you could just read everything into memory at once and work on it in memory. Your code is easy to map via a dict.
Here's a function that takes a filename and converts your file into a dictionary.
def create_mapping(filename):
with open(filename, 'r') as infile:
data = infile.readlines()
mapping = {int(k): (i,d) for k,i,d in
(x.strip().split('|') for x in data)}
# Your mapping now looks like
# { 312: ('cheeseburger', 'Denmark'),
# 621: ('chesscake', 'USA') }
return mapping
Then you can update the mapping from user input since it's just a dictionary.
Once you want to write the file out, you can just serialize out your dictionary by iterating over the keys and rejoining all the elements using |.
If you want to use lists
If you want to stick with just using lists for everything, that is possible.
I would still recommend reading your file into a list, like so:
def load_file(filename):
with open(filename, 'r') as infile:
data = infile.readlines()
items = [(int(k), i, d) for k,i,d in
(x.strip().split('|') for x in data]
# Your list now looks like
# [(312, 'cheeseburger', 'Denmark'), (621, 'chesscake', 'USA')]
return items
Then when you get some user input, you have to traverse the list and find the tuple with what you want inside.
For example, say the user entered code 312, you could find the tuple that contained the 312 value from the list of tuples with this:
items = load_file(filename)
# Get input for 'code' from user
code = int(input(">> "))
# Get the position in the list where the item with this code is
try:
list_position = [item[0] for item in items].index(code)
# Do whatever you need to (ask for more input?)
# If you have to overwrite the element, just reassign its
# position in the list with
# items[list_position] = (code, blah, blah)
except IndexError:
# This means that the user's entered code wasn't entered
# Here you do what you need to (maybe add a new item to the list),
# but I'm just going to pass
pass

Related

Why is it giving me a no index error? when all my indexes are fine in python?

The output is "list index put of range" whenever I run it.
I need to store each of the fields into their own list. So I should have three fields, one for rank, one for power, and one for the number of those cards.
This is the file, that is called "ranks.dat":
Admiral,30,1 General,25,1 Colonel,20,2 Major,15,2 Captain,10,2 Lieutenant,7,2 Sergeant,5,4 Corporal,3,6 Private,1,10
Here is my code:
numFile = open("ranks.dat", "r")
rankList = []
skillList = []
powerList = []
while True:
text = numFile.readline()
text = text.rstrip("\n")
if text=="":
break
info = text.split(" ")
rankList.append(info[0])
skillList.append(int(info[1]))
powerList.append(int(info[2]))
numFile.close()
print("Admiral\tGeneral\tColonel\tMajor\tCaptain\tLieutenant\tSergeant\tCorporal\tPrivate")
Why is it not working?
Assuming that your data has one entry per line:
rankList = []
skillList = []
powerList = []
# recommended way to open and close a file
with open("ranks.dat", "r") as file:
# iterate over every lines in the file
for line in file.readlines():
# unpack each lines
rank, skill, power = line.split(',')
rankList.append(rank)
skillList.append(skill)
powerList.append(power)
The code is contain some mistakes.
First of all it should not be inside a while loop, but (if at all) in for line in text.
Secondly, when you split(" "), you get a list that every item in it contain string in form of "RANK,SKILL,POWER". You should split it every comma, and then append the items to the lists.
And finally, i would highly recommend to check the validity of the input (like checking that there are three items in the splitted info).
Something like that:
rankList = []
skillList = []
powerList = []
fil = open("ranks.dat", "r")
data = fil.read()
fil.close()
for item in data.split():
info = item.split(',')
if len(info) != 3:
continue
rankList.append(info[0])
skillList.append(int(info[1]))
powerList.append(int(info[2]))
# and do whatever you want
It depend on the source of the file, but a complete and correct code will check first if the file exists, and if the values of the rank and skills and the power are valid

Appending to a list from a for loop (to read a text file)

How do I append to an undetermined list from a for loop?
The purpose is to first slice each line by '-'. Then I would like to append these slices to an array without a determined size. I have the following code, and am loosing hair because of how simple this seems!
Each line in the text file looks like the following:
2014-06-13,42.7,-73.8,27
program so far:
f = open('Lightning.txt')
lightning =list()
for templine in f:
if not templine.startswith('2014'): continue
templine = templine.rstrip('-')
line = templine.split()
print line[2]
Thank you community,
Try something like that if you want to get list of formated strings.
f = open('Lightning.txt')
lightning =list()
for templine in f:
if not templine.startswith('2014'): continue
# We are splitting the line by ',' to get [2014-06-13, 42.7,-73.8, 27]
templine = templine.split(',')
# After splitting is done, we know that at the 1st place is the date,
# and at the last one is the number of video recordings.
#Here we asign the first item to "data" and the last one to "num_of_strikes"
date, num_of_strikes = templine[0], templine[-1]
# After that is done, we create the output string with placeholders
# {data} and {num} waiting for data to be passed
output = '{date} : {num} lightning strikes were recorded.'
# Here we are appending the formated string, passing our data to placeholders
# And yes, they work like a dictionary, so u can write (key = value)
lightning.append(output.format(date= date, num= num_of_strikes))
This is an ideal job for the csv lib:
import csv
with open('Lightning.txt') as f:
data = []
# unpack the elements from each line/row
for dte, _, _, i in csv.reader(f):
# if the date starts with 2014, add the date string and the last element i
if dte.startswith('2014'):
data.append((dte, i))
Which can all be done using a list comp:
import csv
with open('Lightning.txt') as f:
data = [(dte, i) for dte, _, _, i in csv.reader(f) if dte.startswith('2014')]

reading a file and parse them into section

okay so I have a file that contains ID number follows by name just like this:
10 alex de souza
11 robin van persie
9 serhat akin
I need to read this file and break each record up into 2 fields the id, and the name. I need to store the entries in a dictionary where ID is the key and the name is the satellite data. Then I need to output, in 2 columns, one entry per line, all the entries in the dictionary, sorted (numerically) by ID. dict.keys and list.sort might be helpful (I guess). Finally the input filename needs to be the first command-line argument.
Thanks for your help!
I have this so far however can't go any further.
fin = open("ids","r") #Read the file
for line in fin: #Split lines
string = str.split()
if len(string) > 1: #Seperate names and grades
id = map(int, string[0]
name = string[1:]
print(id, name) #Print results
We need sys.argv to get the command line argument (careful, the name of the script is always the 0th element of the returned list).
Now we open the file (no error handling, you should add that) and read in the lines individually. Now we have 'number firstname secondname'-strings for each line in the list "lines".
Then open an empty dictionary out and loop over the individual strings in lines, splitting them every space and storing them in the temporary variable tmp (which is now a list of strings: ('number', 'firstname','secondname')).
Following that we just fill the dictionary, using the number as key and the space-joined rest of the names as value.
To print the dictionary sorted just loop over the list of numbers returned by sorted(out), using the key=int option for numerical sorting. Then print the id (the number) and then the corresponding value by calling the dictionary with a string representation of the id.
import sys
try:
infile = sys.argv[1]
except IndexError:
infile = input('Enter file name: ')
with open(infile, 'r') as file:
lines = file.readlines()
out = {}
for fullstr in lines:
tmp = fullstr.split()
out[tmp[0]] = ' '.join(tmp[1:])
for id in sorted(out, key=int):
print id, out[str(id)]
This works for python 2.7 with ASCII-strings. I'm pretty sure that it should be able to handle other encodings as well (German Umlaute work at least), but I can't test that any further. You may also want to add a lot of error handling in case the input file is somehow formatted differently.
Just a suggestion, this code is probably simpler than the other code posted:
import sys
with open(sys.argv[1], "r") as handle:
lines = handle.readlines()
data = dict([i.strip().split(' ', 1) for i in lines])
for idx in sorted(data, key=int):
print idx, data[idx]

Python reading file problems

highest_score = 0
g = open("grades_single.txt","r")
arrayList = []
for line in highest_score:
if float(highest_score) > highest_score:
arrayList.extend(line.split())
g.close()
print(highest_score)
Hello, wondered if anyone could help me , I'm having problems here. I have to read in a file of which contains 3 lines. First line is no use and nor is the 3rd. The second contains a list of letters, to which I have to pull them out (for instance all the As all the Bs all the Cs all the way upto G) there are multiple letters of each. I have to be able to count how many off each through this program. I'm very new to this so please bear with me if the coding created is wrong. Just wondered if anyone could point me in the right direction of how to pull out these letters on the second line and count them. I then have to do a mathamatical function with these letters but I hope to work that out for myself.
Sample of the data:
GTSDF60000
ADCBCBBCADEBCCBADGAACDCCBEDCBACCFEABBCBBBCCEAABCBB
*
You do not read the contents of the file. To do so use the .read() or .readlines() method on your opened file. .readlines() reads each line in a file seperately like so:
g = open("grades_single.txt","r")
filecontent = g.readlines()
since it is good practice to directly close your file after opening it and reading its contents, directly follow with:
g.close()
another option would be:
with open("grades_single.txt","r") as g:
content = g.readlines()
the with-statement closes the file for you (so you don't need to use the .close()-method this way.
Since you need the contents of the second line only you can choose that one directly:
content = g.readlines()[1]
.readlines() doesn't strip a line of is newline(which usually is: \n), so you still have to do so:
content = g.readlines()[1].strip('\n')
The .count()-method lets you count items in a list or in a string. So you could do:
dct = {}
for item in content:
dct[item] = content.count(item)
this can be made more efficient by using a dictionary-comprehension:
dct = {item:content.count(item) for item in content}
at last you can get the highest score and print it:
highest_score = max(dct.values())
print(highest_score)
.values() returns the values of a dictionary and max, well, returns the maximum value in a list.
Thus the code that does what you're looking for could be:
with open("grades_single.txt","r") as g:
content = g.readlines()[1].strip('\n')
dct = {item:content.count(item) for item in content}
highest_score = max(dct.values())
print(highest_score)
highest_score = 0
arrayList = []
with open("grades_single.txt") as f:
arraylist.extend(f[1])
print (arrayList)
This will show you the second line of that file. It will extend arrayList then you can do whatever you want with that list.
import re
# opens the file in read mode (and closes it automatically when done)
with open('my_file.txt', 'r') as opened_file:
# Temporarily stores all lines of the file here.
all_lines_list = []
for line in opened_file.readlines():
all_lines_list.append(line)
# This is the selected pattern.
# It basically means "match a single character from a to g"
# and ignores upper or lower case
pattern = re.compile(r'[a-g]', re.IGNORECASE)
# Which line i want to choose (assuming you only need one line chosen)
line_num_i_need = 2
# (1 is deducted since the first element in python has index 0)
matches = re.findall(pattern, all_lines_list[line_num_i_need-1])
print('\nMatches found:')
print(matches)
print('\nTotal matches:')
print(len(matches))
You might want to check regular expressions in case you need some more complex pattern.
To count the occurrences of each letter I used a dictionary instead of a list. With a dictionary, you can access each letter count later on.
d = {}
g = open("grades_single.txt", "r")
for i,line in enumerate(g):
if i == 1:
holder = list(line.strip())
g.close()
for letter in holder:
d[letter] = holder.count(letter)
for key,value in d.iteritems():
print("{},{}").format(key,value)
Outputs
A,9
C,15
B,15
E,4
D,5
G,1
F,1
One can treat the first line specially (and in this case ignore it) with next inside try: except StopIteration:. In this case, where you only want the second line, follow with another next instead of a for loop.
with open("grades_single.txt") as f:
try:
next(f) # discard 1st line
line = next(f)
except StopIteration:
raise ValueError('file does not even have two lines')
# now use line

Python: Compare List with a List in File

I am strugling with this problem that looks simple but I'm stuck! Well, I have to build a function where I receive a list of categories like:
input Example1: ['point_of_interest', 'natural_feature', 'park', 'establishment']
input Example2: ['point_of_interest', 'establishment']
input Example3: ['sublocality', 'political']
So that list could be with variable elements inside I guess from 1 till 4 not more
So with this same data I am gonna create a file with that input in a way that if the new input is not in the file, append it to the file.
The way is each list is an element itself, I mean I have to compare the full elements of the list and if I can find other list exactly equal I don´t have to add it.
In my code I just tried to add the first element in the file because really I don't know how to add the full list to compare with the next list.
def categories(category):
number = 0
repeat = False
if os.path.exists("routes/svm/categories"):
with open('routes/svm/categories', 'rb') as csvfile:
spamreader = csv.reader(csvfile)
for categoryFile in spamreader:
if (cmp(categoryFile,category) == 0):
number += 1
repeat = True
if not repeat:
categoriesFile = open('routes/svm/categories', 'a')
category = str(category[0])
categoriesFile.write(category)
categoriesFile.write('\n')
categoriesFile.close()
else:
categoriesFile = open('routes/svm/categories', 'w')
category = str(category[0])
categoriesFile.write(category)
categoriesFile.write('\n')
categoriesFile.close()
EDIT: Some explanation by #KlausWarzecha: Users might enter a list with (about 4) items. If this list ( = this combination of items) is not in the file already, you want to add the list (and not the items separately!) to the file? –
The problem is really simple. You may take the following approach if it works for you:
Read all the contents of the CSV into a list
Add all the non-matching items from the input into this list
re-write the CSV file
You may start with this sample code:
# input_list here represents the inputs
# You may get input from some other source too
input_list = [['point_of_interest', 'natural_feature', 'park', 'establishment'], ['point_of_interest', 'establishment'], ['sublocality', 'political']]
category_list = []
with open('routes/svm/categories', 'rb') as csvfile:
spamreader = csv.reader(csvfile)
for categoryFile in spamreader:
print categoryFile
category_list.append(categoryFile)
for item in input_list:
if (item in category_list):
print "Found"
else:
category_list.append(item)
print "Not Found"
# Write `category_list` to the CSV file
Please use this code as a starting point and not as a copy-paste solution.

Categories

Resources