If statement only iterating over 1st line - python-2.7

When printing row in a csv file, how do you get it to iterate over the entire csv instead of one line at a time when performing an if statement? For example:
import csv
nameid = raw_input("ID please")
with open('cards.csv', 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
for row in reader:
row = list(row)
if nameid == row[0]:
print row
else:
print "sorry"
with this csv:
101,8
102,10
103,5
104,0
will use only the first line, then the second line, and so on, giving me a false statement 3 out of 4 times. So if I search for "102" in my raw_input, it will print:
"sorry"
['102', '10']
"sorry"
"sorry

You're actually very close to your intended functionality. You don't want to print "sorry" for every line that doesn't match, so you don't want that else block where it is. But you do want to print "sorry" if nothing at all in the file matches. As it turns out, you can just scoot that else block over one level to the left and have it correspond to the for block instead of the if. You'll also need one extra line:
import csv
nameid = raw_input("ID please")
with open('cards.csv', 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
for row in reader:
row = list(row)
if nameid == row[0]:
print row
break
else:
print "sorry"
Now the else block is only triggered if the for block runs to completion (more info on this syntax here). To make sure it only runs to completion if there are no matches, add the break to immediately exit the loop when you see a match.

It's not giving you a false statement each time. You are iterating through the csv and checking every row's first element against the input. If it doesn't match, you print 'sorry'. If it does, you print the row.
If you want to only print a 'sorry' message if no matches are found, get rid of your else clause. Instead, set a boolean flag that gets initialized as false and only set to true when a match is found. After your iteration is complete, only print the 'sorry' message if the boolean is still false.

Related

how to get corresponding value in CSV through a list

here is my problem, I tend to get corresponding value in CSV through a list. For example:
I have a list like
namelist=[1,2]
and csv like
name id value
1 a aaa
2 b bbb
3 c ccc
and i tend to using every element in the list to find corresponding value in CSV. such as: 1-aaa;2-bbb. this is what i tried now:
with open('1.csv','rb') as f:
reader = csv.DictReader(f)
for i in namelist:
for row in reader:
if row['name'] == namelist[i]:
print row['value']
but I got nothing. how can i fix it?
Thanks in advance!
A couple things:
csv.DictReader reads items to a dictionary of string:string, not string:int. So, I changed your namelist to a list of strings. Alternatively, you could convert row['name'] to an integer, but I figured it would be more versatile converting your namelist in this manner.
It would be much faster to just check if row['name'] in namelist: then to loop over the entire csv file for every element in namelist.
Code:
import csv
namelist=['1','2']
with open('1.csv','rb') as f:
reader = csv.DictReader(f)
for row in reader:
if row['name'] in namelist:
print row['value']
Output:
aaa
bbb
First of all you should use indents after "with" clause. And another thing that can cause problem may be in this part of code:
for i in namelist: # in that case if namelist = [1,2] i will be 1 or 2, but you need 0,1
Also you can try this solution if the order of the columns is always such (i mean name,id,value):
namelist=[1,2]
with open('1.csv','rb') as f:
reader = list(csv.reader(f))
for row in reader:
for i in range(len(namelist)): # or if row[0] in namelist:
if row[0] == namelist[i]:
print row[2]

how to get rid of the space between first and second element? and how to create a "if" statement for selecting information?

19.7435
,5281813.4260,536064.1543,0.371886,out04-36-48-12.tif
lines = f.readlines()
for items in lines:
items = items.replace("\n", "")
#print items
new_file = items.split(",")
new_list_project = ','.join(new_file)
new_list_project = new_list_project.rstrip()
print new_list_project
it always looks like this, but i already used rstrip to remove \n.
19.7435
,5281813.4260,536064.1543,0.371886,out04-36-48-12.tif
also i wanted to select the last element based upon the value of third (0.371886). i write statement but none of them working.
This list has 2000 elements. I might be use for and if statement i guess.
I guess you just have to remove \n after the words. The following code should do it.
f = open("sample.txt")
lines = f.readlines()
for items in lines:
items = [item.strip() for item in items.split(",")]
if items[3] == "0.371886":
print ",".join(items)
else:
print "Whatever you want"
Assuming your file content is:
Elevation, Easting, Northing, Blur metric, Imagery
19.8091 ,5281850.4252,536047.6051,0.335554,out04-32-44-03.tif
19.7435 ,5281813.4260,536064.1543,0.371886,out04-36-48-12.tif
19.8256 ,5281850.5974,536047.2831,0.337232,out04-32-44-15.tif
19.8420 ,5281850.7696,536046.9611,0.4184,out04-32-44-27.tif
19.8584 ,5281850.9418,536046.6392,0.311989,out04-32-44-39.tif
Output:
Whatever you want
Whatever you want
19.7435,5281813.4260,536064.1543,0.371886,out04-36-48-12.tif
Whatever you want
Whatever you want
Whatever you want
If you want to remove the space between first and second element
Try this :
with open("file.txt") as f:
print("".join([i.replace(' ','') for i in f]))
I assumed your data is in a file called "file.txt" .

Merge CSV row with a string match from a 2nd CSV file

I'm working with two large files; approximately 100K+ rows each and I want to search csv file #1 for a string contained in csv file#2, then join another string from csv file#1 to the row in csv file#2 based on the match criteria. Here's an example of the data I'm working with and my expected output:
File#1: String to be matched in file#2 is the 2nd element; 1st is to be appended to each matched row in file#2. (Integer to be appended is bold; string to be matched is italicized for clarity only)
row 1:
3604430123,mta0000cadd503c.mta.net
row 2:
3604434567,mta0000CADD5638.MTA.NET
row 3:
3606304758,mta00069234e9a51.DT.COM
File#2:
row 1:
4246,211-015617,mta0000cadd503c.mta.net,old,NW MG2,BBand2 ESA,Active
row 2:
7251,ACCOUNT,mta0000CADD5638.MTA.NET,FQDN ,NW MG2,BBand2 ESA,Active
row 3:
536887946,874-22558501,mta00069234e9a51.DT.COM,"P",NW MG2,BBand2 ESA,Active
Desired Output joining bold integer string from file#1 to entire row in file#2 based on string match between file#1 and file#2:
row 1:
4246,211-015617,mta0000cadd503c.mta.net,old,NW MG2,BBand2 ESA,Active,3604430123
row 2:
7251,ACCOUNT,mta0000CADD5638.MTA.NET,FQDN ,NW MG2,BBand2 ESA,Active,3604434567
row 3:
536887946,874-22558501,mta00069234e9a51.DT.COM,"P",NW MG2,BBand2 ESA,Active,3606304758
There are many instances where the case in the match string of file#1 doesn't match the case of file#2, however the characters match, thus case can be ignored for match critera. The character case does need to be preserved in file#2 after it is appended with the integer string from file#1.
I'm a python newb and I've been at this for a while and have scoured posts in SE, but can't seem to come up with working code that gets me to the point where I can just print out a line from file#2 that has been matched on the string in file#1. I've tried a few other methods, such as writing to a dictionary, using Dictreader, etc, but haven't been able to clear what appears to be simple errors in those methods, so I tried to strip this down to simple lists and get to the point where I can use a list comprehension to combine the data, then write that back to a file named output, which will eventually be written back to a csv file. Any help or suggestions would be greatly appreciated.
import csv
sg = []
fqdn = []
output = []
with open(r'file2.csv', 'rb') as src:
read = csv.reader(src, delimiter=',')
for row in read:
sg.append(row)
with open(r'file1.csv', 'rb') as src1:
read1 = csv.reader(src1, delimiter=',')
for row in read1:
fqdn.append(row)
output = output.append([s[0] for s in sg if fqdn[1] in sg])
print output
Result after running this is:
None
Process finished with exit code 0
You should use a dictionary for file#1 than just a list, as matching is easier. Just turn fqdn into a dict and in your loop reading file#1 set your key-value pairs on the dict. I would use .lower() on the match key. This turns the key to lower case so you later only have to check if the lower-cased version of the field in file#2 is a key in the dictionary:
import csv
sg = []
fqdn = {}
output = []
with open(r'file2.csv', 'rb') as src:
read = csv.reader(src, delimiter=',')
for dataset in read:
sg.append(dataset)
with open(r'file1.csv', 'rb') as src1:
read1 = csv.reader(src1, delimiter=',')
for to_append, to_match in read1:
fqdn[to_match.lower()] = to_append
for dataset in sg:
to_append = fqdn.get(dataset[2].lower()) # If the key matched, to_append now contains the string to append, else it becomes None
if to_append:
dataset.append(to_append) # Append the field
output.append(dataset) # Append the row to the result list
print(output)
You can then use csv.writer to create a csv file from the result.
Here's a brute force solution to solving this problem. For every line of the first file, you will search through every line of the second file until you find a match. The matched lines will be written out to the output.csv file in the format you specified using the csv writer.
import csv
with open('file1.csv', 'r') as file1:
with open('file2.csv', 'r') as file2:
with open('output.csv', 'w') as outfile:
writer = csv.writer(outfile)
reader1 = csv.reader(file1)
reader2 = csv.reader(file2)
for row in reader1:
if not row:
continue
for other_row in reader2:
if not other_row:
continue
# if we found a match, let's write it to the csv file with the id appended
if row[1].lower() == other_row[2].lower():
new_row = other_row
new_row.append(row[0])
writer.writerow(new_row)
continue
# reset file pointer to beginning of file
file2.seek(0)
You might be tempted to store the information in a data structure before writing it out to a file. In my experience, you always end up getting larger files in the future and may run into memory issues. I like to write things out to file as I find the matches in order to avoid this problem.

IndexError: list index out of range for list of lists in for loop

I've looked at the other questions posted on the site about index error, but I'm still not understanding how to fix my own code. Im a beginner when it comes to Python. Based on the users input, I want to check if that input lies in the fourth position of each line in the list of lists.
Here's the code:
#create a list of lists from the missionPlan.txt
from __future__ import with_statement
listoflists = []
with open("missionPlan.txt", "r") as f:
results = [elem for elem in f.read().split('\n') if elem]
for result in results:
listoflists.append(result.split())
#print(listoflists)
#print(listoflists[2][3])
choice = int(input('Which command would you like to alter: '))
i = 0
for rows in listoflists:
while i < len(listoflists):
if listoflists[i][3]==choice:
print (listoflists[i][0])
i += 1
This is the error I keep getting:
not getting inside the if statement
So, I think this is what you're trying to do - find any line in your "missionPlan.txt" where the 4th word (after splitting on whitespace) matches the number that was input, and print the first word of such lines.
If that is indeed accurate, then perhaps something along this line would be a better approach.
choice = int(input('Which command would you like to alter: '))
allrecords = []
with open("missionPlan.txt", "r") as f:
for line in f:
words = line.split()
allrecords.append(words)
try:
if len(words) > 3 and int(words[3]) == choice:
print words[0]
except ValueError:
pass
Also, if, as your tags suggest, you are using Python 3.x, I'm fairly certain the from __future__ import with_statement isn't particularly necessary...
EDIT: added a couple lines based on comments below. Now in addition to examining every line as it's read, and printing the first field from every line that has a fourth field matching the input, it gathers each line into the allrecords list, split into separate words as a list - corresponding to the original questions listoflists. This will enable further processing on the file later on in the code. Also fixed one glaring mistake - need to split line into words, not f...
Also, to answer your "I cant seem to get inside that if statement" observation - that's because you're comparing a string (listoflists[i][3]) with an integer (choice). The code above addresses both that comparison mismatch and the check for there actually being enough words in a line to do the comparison meaningfully...

Python if statement skipping code even though condition is met

I am trying to check if an entry is already in the database and add the entry if it isn't but the if statement never runs even though the condition is met.
userCurs.execute("SELECT EXISTS(SELECT 1 FROM images WHERE imageLink=?)", (image,))
exists = userCurs.fetchone()
if exists is None:
addImage(userName,image,'','')
else:
print '--------> image skipped'
print userCurs.fetchone()
I get this output:
--------> image skipped
None
--------> image skipped
None
and no entries are made to the database
The SQL statement:
SELECT EXISTS(SELECT 1 FROM images WHERE imageLink=?)
will always return a single row. The value of the column in that row will be the result of the EXISTS() function, which will be TRUE if any matches are found, or FALSE otherwise.
Since your original code only tested for the existence of a row in the result, and the full statement will always return exactly one row, you get the behavior you see.
What I think you should do is have your query return a rowset that has zero rows if no matches are found, and one (or more) rows if matches are found:
userCurs.execute("SELECT 1 FROM images WHERE imageLink=?", (image,))
Now your original test should work - if no imageLinks match the query, then there will be no rows in the result, so the first fetchone() will return a null object as you expect.
Of course, as several others have mentioned, you should ony call fetchone() once per row since it moves the cursor.
Solved it by changing the code to
userCurs.execute("SELECT EXISTS(SELECT 1 FROM images WHERE imageLink=?)", (image,))
exists = userCurs.fetchone()
if exists[0] == 0:
addImage(userName,image,'','')
else:
print '--------> image skipped'
print exists
As people have said the calling fetchone() twice gives different results the actual value of exists was (0,)
Don't call cursor.fetchone() again; the next row is always empty. Reuse the variable. You are fetching a (0,) or (1,) tuple; you could use tuple assignment to extract the flag value (note the comma on exits, =):
exists, = userCurs.fetchone()
if not exists:
addImage(userName, image, '', '')
else:
print '--------> image skipped'
print exists
Now exists will be set to 0 or 1, rather than (0,) or (1,) and the if not exists: test will not pass for the 0 case.