I am trying to find a way to detect when string elements in csv file change values. When the value changes, I want the operation of the program to change. I want to read the value in the for loop one step ahead and compare it to the current value. Unfortunately my research has only turn up results that step the for loop ahead by one rather than simply reading the value.
Any help would be appropriated.
import csv
with open("bleh.csv", "r") as bleh:
blehFileReader = csv.reader(bleh, delimiter=',')
next(blehFileReader, None)
for row in blehFileReader:
name = row
nextname = next(blehFileReader)
print(name)
if name != nextname:
print ("name has changed")
Instead of looking at the next name, look at the previous one:
previous_name = None
for row in blehFileReader:
if row != previous_name:
print ("name has changed")
....
previous_name = row
Related
my code:
import csv
with open('file.csv', 'r') as information:
reader = csv.reader(information, delimiter=';')
for row in reader:
print('Highest score is: {} on {} by {}'.format(row[2], row[1], row[0]))
information in csv file:
Anton;12-05-2016;29
Douwe Bob;13-05-2016;44
Anton;11-05-2016;39
Douwe Bob;12-05-2016;55
Anton;10-05-2016;29
Douwe Bob;11-05-2016;69
When I run the program i'll get all lines printed without the max score. I try'd max(row[2]) but seems not to work, there must be somthing im doing wrong. Anyone that can help me out?
I only want to get the line printed with the max score row[2]
For those that start crying we're not going to make your homework stay away, i just want to improve my programming skills!
def get_score_from_row(row):
return float(row[-1])
max_score_row = max(csv.reader(information, delimiter=';'),key=get_score_from_row)
should give you the line with the max score
Here's how I worked this. I created a new list to store the numbers and then since the row is a list itself, accessed the number element location and stored it into the new list.
import csv
# create a new list to store only the numbers
my_list = []
with open('C:\\Users\\mnickey\\Documents\\names.txt', 'r') as information:
reader = csv.reader(information, delimiter=';')
for row in reader:
# used to assure that the row in the reader is a list
print(type(row))
# assuming that you know where the numbers are in the file
num = row[2]
# append this to the empty list
my_list.append(num)
print(max(my_list))
I hope this helps. Note that it's likely not as advanced or efficient as others might post but it should work.
I'm trying to do different checks based on the index number of a dictionary. So, if index == 0, do something, otherwise if index>0, do something else.
I was trying to use OrderedDict and index it based on items(). But if I say, od.items()[0], it just gives me the name of the first element. Not the ability to write an if conditional based on whether the first element has already been checked.
Also I would prefer not to check my conditional based on the actual value in the example.csv file, since it will change daily.
Here is my code and example data in the csv file.
Example.csv
Key_abc, Value894
Key_xyz, Value256
Key_hju, Value_567
Code:
with open('example.csv','rb') as f:
r = csv.reader(f)
od = collections.OrderedDict(r)
for row in od:
if od.items() == 0:
print 'do some checks and run code'
print row, od[row]
elif od.items() > 0:
print 'go through code without checks'
print row, od[row]
Maybe you could do something like this. (The example below is written in python3 syntax).
#ExampleCode
with open('example.csv') as f:
r = csv.reader(f)
od = collections.OrderedDict(r)
for index, row in zip(collections.count(), od):
if index == 0:
print('do some checks and run code')
print(row, od[row])
elif index > 0:
print('go through code without checks')
print(row, od[row])
Simple question: i've got this code:
i want to fetch a row with Dictreader from the csv package, every entry i wanto to cast it float and put it in the data array. At the end of the scanning i want to print the first 10 elements of the array. It gives me error of visibility on the array data.
with open(train, "r") as traincsv:
trainreader = csv.DictReader(traincsv)
for row in trainreader:
data = [float(row['Sales'])]
print(data[:10])
If i put the print inside the for like this
with open(train, "r") as traincsv:
trainreader = csv.DictReader(traincsv)
for row in trainreader:
data = [float(row['Sales'])]
print(data[:10])
It prints all the entries not just 10.
You are overwriting data every time in the for loop. This is the source of your problem.
Please upload an example input for me to try and I will, but I believe what is below will fix your problem, by appending to data instead of overwriting it.
Also, it is good practice to leave the with block as soon as possible.
# Open with block and leave immediately
with open(train, "r") as traincsv:
trainreader = csv.DictReader(traincsv)
# Declare data as a blank list before iterations
data =[]
# Iterate through all of trainreader
for row in trainreader:
data.append([float(row['Sales'])])
# Now it should print first 10 results
print(data[:10])
Ways of appending a list:
data = data + [float(row['Sales'])]
data += [float(row['Sales'])]
data.append([float(row['Sales'])]
There is an error in my code :
_csv.Error: sequence expected
which i believe is because i am trying to write only one value not a list etc.
exRtFile = open ('exchangeRate.csv')
exchReader = csv.reader(exRtFile)
exchWriter = csv.writer(exRtFile)
loop2=0
while loop2==0:
selected=int(input("Please select an option: "))
if selected == 1:
change = input("What rate would you like to change: ")
changeRt = float(input("What would you like to change the rate to: "))
for row in exchReader:
currency = row[0]
if currency == change:
crntRt = row[1]
crntRt = changeRt
exchWriter.writerow(crntRt)
exRtFile.close()
what would be the best way to fix this, or is there a better wayy to change a value in an CSV file?
csv file:
Pound Sterling,1
Euro,1.22
US Dollar,1.67
Japanese Yen,169.948
Here is some code, not tested, that will do what you want. The idea is to read the text into memory, apply the updates, then write out the results over the original file.
You can further enhance this ask the user if they want to save their changes, and to add new currencies instead of just telling the user they're not known.
In the real world, I would break this code into three separate functions (or even classes), one for reading, one for writing, and one for editing the list.
import csv
rates = {}
# read file into dictionary
with open('csv_file.csv', 'r') as in_file:
rdr = csv.reader(in_file)
for item in reader:
rates[row[0]] = row[1]
# ask user for updates and apply to dictionary
while true:
cmd = raw_input('Enter exchange rate to adjust, or blank to exit')
if cmd is None or cmd.strip() == '':
break
if rates.has_key(cmd):
new_rate = float(raw_input('Enter new exchange rate:'))
rates[cmd] = new_rate
else:
print 'Currency {} is not known.'.format(cmd)
# Write the updated dictionary back over the same file.
with open('csv_file.csv', 'w') as out_file:
wrtr = csv_writer(out_file)
wrtr.writerows(rates)
Answering your question: Yes, the problem is that you were trying to write only a value, while writerow expects a list.
That said... Would you consider changing a bit the way your code works?
Here's what I've done (I've tested it now, so I know it works):
First, ask the user for all the changes to make and keep them in a dict where keys are the currency names (Euro, for instance) and the value is the new currency value (5.0, for instance) The user can get out of the loop pressing 0
Second, open and read your exchangeRate.csv file row by row. If the row[0] (name of the currency) is among the values to change, then change it in that row.
No matter what happens (regardless of whether the row needed to be changed or not) write that row in a new temporary file exchangeRate.csv.tmp
When all the rows in the original file are read, you'll have exchangeRate.csv.tmp with some rows unchanged and some rows changed. Swap (move) the .tmp file to exchangeRate.csv
Dunno... might be too much change maybe? Here it is, anyway:
import csv
import shutil
change_rates = {}
selected = 1
while selected:
selected=int(raw_input("Please select an option: (1 to change, 0 to exit)"))
if selected == 1:
change = raw_input("What rate would you like to change?: ")
changeRt = float(raw_input("What would you like to change the rate to: "))
change_rates[change] = changeRt
if len(change_rates) > 0:
with open('exchangeRate.csv', 'r') as f_in,\
open('exchangeRate.csv.tmp', 'w') as f_out:
exchReader = csv.reader(f_in)
exchWriter = csv.writer(f_out)
for row in exchReader:
if row[0] in change_rates:
row[1] = change_rates[row[0]]
exchWriter.writerow(row)
shutil.move('exchangeRate.csv.tmp', 'exchangeRate.csv')
And a sample execution below:
Please select an option: (1 to change, 0 to exit)1
What rate would you like to change?: Euro
What would you like to change the rate to: 5
Please select an option: (1 to change, 0 to exit)0
borrajax#borrajax:~/Documents/Tests$ cat ./exchangeRate.csv
Pound Sterling,1
Euro,5.0
US Dollar,1.67
Japanese Yen,169.948
You can always make more optimizations, such as... allow case insensitive searches, or check that the currency has actually been changed (like even if the user says he wants to change the currency Euro to 5.0, if that was the Euro's exchange rate then don't do anything)... Things like that.
EDIT 1:
I've just seen Larry Lustig's answer and I agree that for small files as it seems to be your case (files that you can fully load in memory) the continuous reading and writing from disk I posted is not optimal. His idea of keeping everything in memory and then do a bulk write to the same exchangeRate.csv file probably is a better fit for your needs.
EDIT 2:
To answer your questions in a comment to this answer:
what does .tmp do at the end of: exchangeRate.csv.tmp:
It's just a new name. I add the suffix .tmp to avoid a naming conflict with your original file (exchangeRate.csv). You could name it whatever you want, though (even foobar.baz)
What is the purpose of 'change' in the variable: change_rates[change] = changeRt:
change is a variable that contains the name of the currency to change (in the usage example I posted, change contains the string "Euro", because that's what the user (erm... me) typed on the console. Is just a way of accessing a dict.
What is the prupose of '[row[0]]' in: row1=change_rates[row[0]].
We agreed that when reading the file, row[0] (just like that, not [row[0]]) contains the name of the currency in the file (Euro, Pound Sterling... etcetera) right? So at a certain point of the execution row[0] will contain the string "Euro", which (in my test example) is the currency the user wanted to change. That string ("Euro") is also a key in the change_rates dictionary (because the user said he wanted to change it) so you are querying the value for the item with key "Euro" in the change_rates dictionary (which will give you 5.0). Is pretty much doing change_rates["Euro"] To see it a bit more clearer add the line print "Currencies to change: %s" % change_rates on the line right above if len(change_rates) > 0: (that'll show you how the dictionary looks like)
what does shutil.move('exchangeRate.csv.tmp', 'exchangeRate.csv') do?
It copies the file with the new currencies to exchangeRate.csv (see the shutil documentation)
I have the following algorithm to parse a column for integer values:
def getddr(ws):
address = []
col_name = 'C'
start_row = 4
end_row = ws.get_highest_row()+1
range_expr = "{col}{start_row}:{col}{end_row}".format(col=col_name, start_row=start_row, end_row=end_row)
for row in ws.iter_rows(range_string=range_expr):
print row
raw_input("enter to continue")
cell = row[0]
if str(cell.value).isdigit:
address.append(cell.value)
else:
continue
return address
This crashes at cell = row[0] saying "IndexError: tuple index out of range", and i dont know what this means. I tried printing out row to see what it contained, but all it gives me is an empty set of parentheses. Anyone know what I'm missing?
That is not so easy to say what is the problem you have, because there are no input data that you are trying to process.
But I can explain what is the reason of the error you've get, and in which direction you must go. The list row contains 0 elements (row = []), because of that you can not say row[0] — there are no row[0]. The first thing you must change is check, how long is your list, and when if it is long enough make other things:
for row in ws.iter_rows(range_string=range_expr):
print row
raw_input("enter to continue")
if len(row) > 0:
cell = row[0]
if str(cell.value).isdigit:
address.append(cell.value)
else:
continue
That is the first step that you must do anyway.