Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
How can I sort by name and age in PYTHON?
I have the following list in .txt file:
John, 14
Mike, 18
Marco, 25
Michael, 33
I want to sort this by name and by age. I wrote this code but it doesn't work:
file = open("people.txt", "r")
data = file.readlines()
i = 0
for line in data:
name, age = line.split(',')
list = [name, age]
i += 1
print("For sorting by name press (1);")
print("For sorting by age press (2);")
z = eval(input())
if z == 1:
list.sort(key=lambda x: x.name, reverse=True)
print([item.name for item in list])
Thank you very much guys :)
Here's one approach:
with open("so.txt", "r") as f:
lines = [line.split(',') for line in f]
print("For sorting by name press (1);")
print("For sorting by age press (2);")
z = int(input())
if z == 1:
lines.sort(key=lambda x: x[0], reverse=True)
print([item[0] for item in lines])
Using:
a context manager to handle automatic file closure (this is the with)
the for line in f iterator to loop over the file's lines one at a time
a list comprehension to split the lines into lists as needed
int instead of eval
changing all line.name references to line[0] -- you could make the lines proper classes (or namedtuples if you wanted the .name access.
Though, in general, solutions for parsing csv files exist (e.g. csv -- there were a few more issues in your code than just that.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Question: Write a program that reads table with given columns from input stream. Columns are name, amount, debt. Then filter the table (condition: debt is equal to 0). After that increase debt by 42% then print results.
I am a beginner in Python and have tried multiple times but still couldn't fixed the problem. Help will be much appreciated.
Input:
10
Tatiana Santos 411889 36881
Yuvraj Holden 121877 0
Theia Nicholson 783887 591951
Raife Padilla 445511 0
Hamaad Millington 818507 276592
Maksim Whitehead 310884 0
Iosif Portillo 773233 0
Lachlan Daniels 115100 0
Evie-Grace Reese 545083 0
Ashlea Cooper 68771 0
Required Output:
Tatiana Santos 411889 52371.02
Theia Nicholson 783887 840570.42
Hamaad Millington 818507 392760.64
My Solution:
def input_data(n):
tup = []
if n>0:
tup.append(tuple(map(str,input().split(" "))))
input_data(n-1) #I know there's a problem in the recursion. I am not #doing anything with the return value. Please help
return tup
def filtertuple(* tup): # After debugged I got to know at this point only one row is passed to function
newtuple = filter(lambda i: i[2]!=0,tup)
return tuple(newtuple)
def increasedebt(newtuple):
newtuple1 = tuple(map(lambda i:(i[2])*(142/100)),newtuple)
return (newtuple1)
def output_data():
n=int(input())
return n
print(increasedebt(filtertuple(input_data(output_data()))))
Error: Traceback (most recent call last):
File "C:\Users\msi-pc\PycharmProjects\ProgramminglanguageTask3\main.py",
line 28, in <module>
print(increasedebt(filtertuple(input_data(output_data()))))
File "C:\Users\msi-pc\PycharmProjects\ProgramminglanguageTask3\main.py",
line 14, in filtertuple
return tuple(newtuple)
File "C:\Users\msi-pc\PycharmProjects\ProgramminglanguageTask3\main.py",
line 12, in <lambda>
newtuple = filter(lambda i: i[2] != 0, tup)
IndexError: list index out of range
I see two main issues with how your code passes the data from input_data to filtertuple.
The first issue is that your recursion in input_data is messed up, you never do anything with the results of the recursive calls so only the first row of input data gets included in the final return value. Recursion really isn't an ideal approach to this problem, a loop would be a lot simpler and cleaner. But you could make the recursion work, if you do something with the value returned to you, like tup.extend(intput_data(n-1)). If you stick with recursion, you'll also need to make the base case return something appropriate (or add an extra check for None), like an empty list (or tuple).
The second issue is that filtertuple is written to expect many arguments, but you're only passing it one. So tup will always be a 1-tuple containing the actual argument. If you're expecting the one argument to be a list of tuples (or tuple of tuples, I'm not sure exactly what API you're aiming for), you shouldn't use *tup in the argument list, just tup is good without the star. You could call filtertuple(*input_data(...)) which would unpack your tuple of tuples into many arguments, but that would be silly if the function is just going to pack them back up into tup again.
There may be other issues further along in the code, I was only focused on the input_data and filtertuple interactions, since that's what you were asking about.
Here's my take on solving your problem:
def gather_data(num_lines):
if num_lines == 0: # base case
return [] # returns an empty list
data = gather_data(num_lines-1) # recursive case, always gives us a list
row = tuple(map(int, input().split(" "))) # get one new row
data.append(row) # add it to the existing list
return data
def filter_zeros(data): # note, we only expect one argument (a list of tuples)
return list(filter(lambda i: i[1] != 0, data))
def adjust_debt(data): # this only returns a single column, should it return
return list(map(lambda i: (i[1]) * (142 / 100), data)) # the whole table?
# calling code:
num_lines = int(input()) # this code really didn't deserve its own function
data = gather_data(num_lines) # extra variables help debugging
filtered = filter_zeros(data) # but they could be dropped later
adjusted = adjust_debt(filtered)
print(adjusted)
I did find one extra issue, you had the parentheses wrong in the function I renamed to adjust_debt.
Input (new.csv:)
student Jack
Choice Phy
Choice Chem
Choice Maths
Choice Biology
student Jill
Choice Phy
Choice Biology
Choice Maths
Expected Output (out.csv)
Student Phy Chem Maths Biology
Jack Yes Yes Yes Yes
Jill Yes No Yes Yes
Parsing new.csv and writing result in out.csv.For each student name, writing YES if a choice of subject is present and NO if the subject is not in the choice(subjects become new header in out.csv).
Here I have used nested if to get desired output.Please help me with better pythonic way of code.
I am newbie to python.Eager to learn better way of coding.
P.S: Choice of subjects is not in the same order.
import csv
la =[]
l2=[]
with open("new.csv","r",newline='\n') as k:
k=csv.reader(k, delimiter=',', quotechar='_', quoting=csv.QUOTE_ALL)
counter = 0
for col in k :
# number of rows in csv is 600
if counter<=600:
if col[0] =='student':
la.append("\n "+col[1])
a=next(k)
if a[1] == 'Phy':
la.append('yes')
a = next(k)
else:
la.append('no')
if a[1] == 'Chem':
la.append('yes')
a = next(k)
else:
la.append('no')
if a[1] == 'Maths':
la.append('yes')
a = next(k)
else:
la.append('no')
if a[1] == 'Biology':
la.append('yes')
a = next(k)
counter += 1
else:
la.append('no')
counter += 1
l2=",".join(la)
with open("out.csv","w") as w:
w.writelines(l2)
IMHO, it is time to learn how to debug simple prorams. Some IDE come with nice debuggers, but you can still use the good old pdb or simply add print traces in your code to easily understand what happens.
Here, the first and most evident problem is here:
tot = sum(1 for col in k)
It is pretty useless because for col in k would be enough, but it consumes the totality of the k iterator, so the next line for col in k: try to access an iterator that has already reached its end and the loop immediately stops.
That is not all:
first line contains Student with an upper case S while you test student with a lower case s: they are different strings... This case problems exists on all the other comparisons.
when you find student, you set a to the line following it... and never change it. So even if you fix your case errors, you will consistently use that only line for the student!
If you are a beginner, the rule is Keep It Simple, Stupid. So start from something you can control and then start to add other features:
read the input file with the csv module and just print the list for every row. Do not step further until this gives what you want! That would have stopped you from the tot = sum(1 for col in k) error...
identify every student. Just print it first, then store its name in a list and print the list after the loop
identify subject. Just print them first, then feed a dictionnary with the subjects
wonder how you can get that at the end of the loop...
just realize that you could store the student name in that dictionnary, and put the full dictionnary in the list (feel free to ask a new question if you are stuck there...)
print the list of dictionnaries at the end of the loop
build one row for student that could feed the csv writer, or as you already have a list of dict, considere using a DictWriter.
Good luck in practicing Python!
Here is a possible way for the read part:
import csv
la = {} # use a dict to use the student name as index
with open("new.csv","r",newline='\n') as k:
k=csv.reader(k, delimiter=',', quotechar='_', quoting=csv.QUOTE_ALL)
# counter = 0 # pretty useless...
for col in k :
if col[0] =='student':
l2 = set() # initialize a set to store subjects
la[col[1]] = l2 # reference it in la indexed by the student's name
else: # it should be a subject line
l2.add(col[1]) # note the subject
# Ok la is a dict with studend names as key, and a set containing subjects for that student as value
print(la)
For the write part, you should:
build an union of all sets to get all the possible subjects (unless you know that)
for each item (name, subjects) from la, build a list storing yes or no for each of the possible subject
write that list to the output csv file
...left as an exercise...
So I have a file with
first name(space)last name(tab)a grade as such.
Example
Wanda Barber 96
I'm having trouble reading this in as a list and then editing the number.
My current code is,
def TopStudents(n):
original = open(n)
contents = original.readlines()
x = contents.split('/t')
for y in x[::2]:
y - 100
if y > 0: (????)
Here is the point where I'm confused. I am just trying to get the first and last names of students who scored over 100%. I thought of creating a new list for students that meet this qualification, but I'm not sure how I would write the corresponding first and last name. I know I need to take the stride of every other location in the list, as odd will always be the first and last names. Thank you in advance for the help!
There are several things wrong with your code:
- The open file must be closed (#1)
- Must be made a function call using to call it (#2)
- The split used is using the forwardslash (/) instead of the backslash () (#3)
- The way you decided to loop through your for loop is not optimal if you are looking to access all the members (#4)
- The for loops end in a : (#5)
- You must store the result of that calculation somewhere (#6)
def TopStudents(n):
original = open(n) #1
contents = original.readlines #2
x = contents.split('/t') #3
for y in x[::2] #4, #5
y - 100 #6
if y > 0:
That said, a fixed version could be:
original = open(n, 'r')
for line in original:
name, score = line.split('\t')
# If needed, you could split the name into first and last name:
# first_name, last_name = name.split(' ')
# 'score' is a string, we must convert it to an int before comparing to one, so...
score = int(score)
if score > 100:
print("The student " + name + " has the score " + str(score))
original.close() #1 - Closed the file
Note: I have focused on readability with several commentary to help you understand the code.
I always prefer to use ‘with open()’ because it closes the file automatically. I used a txt with comma separations for simplicity for me, but you can just replace the comma with \t.
def TopStudents():
with open('temp.txt', 'r') as original:
contents = list(filter(None, (line.strip().strip('\n') for line in original)))
x = list(part.split(',') for part in contents)
for y in x:
if int(y[1]) > 100:
print(y[0], y[1])
TopStudents()
This opens and loads all lines into contents as a list, removing blank lines and line breaks. Then it separates into a list of lists.
You then iterate through each list in x, looking for the second value (y[1]) which is your grade. If the int() is greater than 100, print each segment of y.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I got a .txt file with some lines in it:
325255, Jan Jansen
334343, Erik Materus
235434, Ali Ahson
645345, Eva Versteeg
534545, Jan de Wilde
345355, Henk de Vries
Write a program that starts with opening the file kaartnummers.txt
Determine the number of lines and the largest card number in the file. Then print these data.
my code isnt finished yet but i tried atleast!:
def kaartinfo():
lst = []
infile = open('kaartnummers.txt', 'r')
content = infile.readlines()
print(len(content))
for i in content:
print(i.split())
kaartinfo()
I know that my program opens the file and counts the number of lines in it.. all after that is wrong <3
I can't figure out how to get the max number in the list.. Please if you got an answer use simple readable Python Language.
I'm not good at python, and there are probably much more elegant solutions, but this is how I would do it. Some may say this is like C++/Java in python, which many tend to avoid.
def kaartinfo():
lst = []
infile = open('kaartnummers.txt', 'r')
content = infile.readlines()
for i in content:
value = i.split(',')
value[0] = int(value[0])
lst.append(value)
return lst
Use the kaartinfo() function to retrieve a list
my_list = kaartinfo()
Assume first value is the maximum
maximumValue = my_list[0][0]
Go through every value in the list, check if they are greater than the current maximum
# if they are, set them as the new current maximum
for ele in my_list:
if ele[0] > maximumValue:
maximumValue = ele[0]
when the above loop finishes, maximum value will be the largest value in the list.
#Convert the integer back to a string, and print the result
print(str(maximumValue) + ' is the maximum value in the file!')
This should be enough to do the job:
with open('kaartnummers.txt', 'r') as f:
data = f.readlines()
print('There are %d lines in the file.' % len(data))
print('Max value is %s.' % max(line.split(',')[0] for line in data))
Given the input file you provided, the output would be:
There are 6 lines in the file.
Max value is 645345.
Of course, you can put it in a function if you like.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
I am dealing with a large txt file, there are overall 8050000 lines. A short example of the lines are:
usedfor zipper fasten_coat
usedfor zipper fasten_jacket
usedfor zipper fasten_pant
usedfor your_foot walk
atlocation camera cupboard
atlocation camera drawer
atlocation camera house
relatedto more plenty
I write a python code to read the lines, and store them as a dictionary. My code is:
dicCSK = {}
for line in finCSK:
line=line.strip('\n')
try:
r, c1, c2 = line.split(" ")
except ValueError: print line
if c1 not in dicCSK.keys():
dicCSK[c1]= []
str1 = r+" "+c2
dicCSK[c1].append(str1)
However, I ran the program for over 20 hours, it is still running. So is there any better way to store them in a dictionary? My code is too slow. Thanks.
This is a mistake: it generates a list of all keys in the dictionary and then scans over it.
if c1 not in dicCSK.keys():
dicCSK[c1]= []
Instead:
if c1 not in dicCSK:
dicCSK[c1] = []
Or instead, use a defaultdict to avoid the check.
dicCSK = collections.defaultdict(list)
for line in finCSK:
line=line.strip('\n')
try:
r, c1, c2 = line.split(" ")
except ValueError:
print line
dicCSK[c1].append(r+" "+c2)
Also, probably you also want the dicCSK[c1].append(r+" "+c2) statement under an else clause of the try/except otherwise it will execute even when there's a ValueError exception.