Python trouble exiting a 'while' loop for simple script - python

I wrote a script to reformat a tab-delimited matrix (with header) into a "long format". See example below. It performs the task correctly but it seems to get stuck in an endless loop...
Example of input:
WHO THING1 THING2
me me1 me2
you you1 you2
Desired output:
me THING1 me1
me THING2 me2
you THING1 you1
you THING2 you2
Here is the code:
import csv
matrix_file = open('path')
matrix_reader = csv.reader(matrix_file, delimiter="\t")
j = 1
while j:
matrix_file.seek(0)
rownum = 0
for i in matrix_reader:
rownum+=1
if j == int(len(i)):
j = False
elif rownum ==1:
header = i[j]
else:
print i[0], "\t",header, "\t",i[j]
j +=1
I think it has to do with my exit command (j = False). Any ideas?
edit: Thanks for suggestions. I think a typo in my initial posting led to some confusion, sorry about that For now I have employed a simple solution:
valid = True
while valid:
matrix_file.seek(0)
rownum = 0
for i in matrix_reader:
rownum+=1
if j == int(len(i)):
valid = False
etc, etc, etc...

Your j += 1 is outside the while loop, so j never increases. If len(i) is never less than 2, then you'll have an infinite loop.
But as has been observed, there are other problems with this code. Here's a working version based on your idiom. I would do a lot of things differently, but perhaps you'll find it useful to see how your code could have worked:
j = 1
while j:
matrix_file.seek(0)
rownum = 0
for i in matrix_reader:
rownum += 1
if j == len(i) or j == -1:
j = -1
elif rownum == 1:
header = i[j]
else:
print i[0], "\t", header, "\t", i[j]
j += 1
It doesn't print the rows in the order you wanted, but it gets the basics right.
Here's how I would do it instead. I see that this is similar to what Ashwini Chaudhary posted, but a bit more generalized:
import csv
matrix_file = open('path')
matrix_reader = csv.reader(matrix_file, delimiter="\t")
headers = next(matrix_reader, '')
for row in matrix_reader:
for header, value in zip(headers[1:], row[1:]):
print row[0], header, value

j+=1 is outside the while loop as senderle's answer says.
other improvements can be:
int(len(i)) ,just use len(i) ,as len() always returns a int so no need of int() around
it
use for rownum,i in enumerate(matrix_reader): so now there's no
need of handling an extra variable rownum, it'll be incremented by
itself.
EDIT: A working version of your code, I don't think there's a need of while here, the for loop is sufficient.
import csv
matrix_file = open('data1.csv')
matrix_reader = csv.reader(matrix_file, delimiter="\t")
header=matrix_reader.next()[0].split() #now header is ['WHO', 'THING1', 'THING2']
for i in matrix_reader:
line=i[0].split()
print line[0], "\t",header[1], "\t",line[1]
print line[0], "\t",header[2], "\t",line[2]

Related

USACO Code Submission Problem - Output File Missing

I've started practicing for the USACO contest tomorrow, I'm relativly new so I'm not too familiar with their input/output methods. Here's the code I submitted to the website
n = int(input())
a = input()
b = input()
swap_number = 0
a_list = []
b_list = []
for i in range(n):
if a[i] != b[i]:
a_list.append(a[i])
b_list.append(b[i])
one_value = 0
two_value = 0
for x in range(len(a_list)):
if a_list[x] == "H":
one_value += 1
else:
two_value += 1
list = [one_value,two_value]
list.sort()
swap_number = list[0] + (list[1]-list[0])
print(swap_number)
after loading for a couple minutes, it displayed:
Your output file breedflip.out:
[File missing!]
I rewrote, retested every problem using this simple code, but still receive the same error
Would this code not create an output file and how can I put the outputted answer in the file
Try to add these two lines in your beginning of codes: (just test and it passed with my revised code) Your code might not be working!
import sys
sys.stdin = open('breedflip.in', 'r')
sys.stdout = open('breedflip.out', 'w')
n = int(input())
a = list(input()) # list
b = list(input())
...........

How to format the output in a better way for geeksforgeeks problems

def doorcheck(n):
doors = []
for i in range(n):
doors.append(False)
for i in range(n):
for x in range(n):
if (x+1) % (i+1) == 0:
if(doors[x] is False):
doors[x] = 1
else:
doors[x] = 0
for i in range(n-1):
print(doors[i], end = ' ')
print(doors[n-1], end = '\n')
t = int(input())
for i in range(t):
n = int(input())
doorcheck(n)
Here I am trying to print each desired output in a separate line.
As asked in the question
Example:
Input:
2
3
5
Output:
1 0 0
1 0 0 1 0
And I have used
for i in range(n-1):
print(doors[i], end = ' ')
print(doors[n-1], end = '\n')
the above code for this purpose. Is there a better way to do it?
Edit 1: The code above I wrote has a bug. But anyways #Barmar has given an excellent solution to my problem, which was about formatting output in a concise manner. And he also gave a suggestion for initializing an array which contains same element throughout its length. Thanks.
If you just want to print the elements of doors separated by spaces, use join()
print(' '.join(map(str, doors)))
You can also replace the loop that initializes doors with:
doors = [False] * n

i have a problem with strings and for loop in python

I have a string and I saved it inside a variable.
I want to change even characters to capitalize with for loop.
so i give my even characters and capitalized it. But
i cant bring them with odd characters .
can someone help me?
here is my code:
name = "mohammadhosein"
>>> for even in range(0, len(name), 2):
... if(even % 2 == 0):
... print(name[even].title(), end=' ')
...
M H M A H S I >>>
>>> ###### I want print it like this:MoHaMmAdHoSeIn```
I assume you are quite new to programing, so use a the following for loop:
name = "mohammadhosein"
output = ''
for i, c in enumerate(name):
if i % 2 == 0:
output += c.upper()
else:
output += c
# output will be 'MoHaMmAdHoSeIn'
enumerate will give you a pair of (i, c) where i is an index, starting at 0, and c is a character of name.
If you feel more comfortable with code you can use a list comprehension and join the results as follows:
>>> ''.join([c.upper() if i % 2 == 0 else c for i, c in enumerate(name)])
'MoHaMmAdHoSeIn'
As #SimonN has suggested, you just needed to make some small changes to your code:
for index in range(0, len(name)):
if(index % 2 == 0):
print(name[index].upper(), end='') # use upper instead of title it is more readable
else:
print(name[index], end='')
print()

Modifying output of for loop in Python

I am looping in through a file as per the code below:
for i in tree.iter():
for j in i:
print(j.col)
print(j.out)
print('\n')
Given below is the current output:
col1
out1
col2
out2
col3
out3
I am trying to have this modified as below:
col1,col2,col3
out1,out2,out3
Could anyone advice on how I could have my for loop modified. Thanks..
You can use this
print(j.col, end=',')
Edit:
By default Python adds an "\n" new line break at the end of print() functions.
You can use the "end" value to change it.
I've made a makeshift version of your code to test it out
j = 0
k = 0
while j < 2:
print("col", end=",")
if j == 1:
print("col")
j += 1
while k < 2:
print("out", end=",")
if k == 1:
print("out")
k += 1
Output:
Python 3.x: save cols and outs into two separate lists and later print their elements (using an asterisk before the list name) separated by a comma:
cols = list()
outs = list()
for i in tree.iter():
for j in i:
cols.append(j.col)
outs.append(j.out)
print(*cols, sep=',')
print(*outs, sep=',')

Removing Line From Python List - All Lines Containing Certain Number

I am looking to remove lines from a list that have a 0 in the 4th position. When I write out the file now it is not eliinating all the zero lines.
counter = 0
for j in all_decisions:
if all_decisions[counter][4] == 0:
all_decisions.remove(j)
counter += 1
ofile = open("non_zero_decisions1.csv","a")
writer = csv.writer(ofile, delimiter=',')
for each in all_decisions:
writer.writerow(each)
ofile.close()
Use a list comprehension.
all_decisions = [x for x in all_decisions if x[4] != 0]
Or, use filter.
all_decisions = filter(lambda x: x[4] != 0, all_decisions)
The way you're doing this is not a good idea because you're modifying all_decisions while you're iterating over it. If you wanted to do it in a loop, I would suggest something like:
temp = []
for x in all_decisions:
if x[4] != 0:
temp.append(x)
all_decisions = temp
But this is basically just a more verbose equivalent of the list comprehension and filter approaches I showed above.
I think the problem is in your loop which eliminates the lines:
counter = 0
for j in all_decisions:
if all_decisions[counter][4] == 0:
all_decisions.remove(j)
counter += 1
If you remove an element, you also bump the counter. The consequence of that is that you're skipping lines. So you might miss lines to be removed. Try only bumping the counter if you didn't remove an element, i.e.
counter = 0
for j in all_decisions:
if all_decisions[counter][4] == 0:
all_decisions.remove(j)
else:
counter += 1
That being said, a more concise way to do what you want would be
with open("non_zero_decisions1.csv","a") as ofile:
writer = csv.writer(ofile, delimiter=',')
writer.writerows(d for d in all_decisions if d[4] != 0)
The with clause will take care of calling close on ofile after executing the code, even if an exception is thrown. Also, csv.writer features a writerows method which takes a list of rows. Thirdly, you can use a generator expression d for d in all_decisions if d[4] != 0 to replace your filtering loop.

Categories

Resources