Reading simple data files manipulating strings. - python

If I'm given:
point_loads, 3, 500
point_loads, 6, 900
point_loads, 12, 300
This code:
for line in open("Input.txt"):
li=line.strip()
if li.startswith("point_load"):
l = li.split(',')
for num in l[1:]:
num = float(num.strip())
point_loads.append(num)
prints:
point_loads = [3, 500, 6, 900, 12, 300]
I am trying to modify it so that if I'm given:
length = 32
point_loads, 3, 500
point_loads, 6, 900
point_loads, end, 300
It will set 'end' equal to 32 (or the variable length) so that the output is:
point_loads = [3, 500, 6, 900, 32, 300]
I tried a few different things, this was my latest...
for line in open("Input.txt"):
li=line.strip()
if li.startswith("point_load"):
l = li.split(',')
for num in l[1:]:
if num == 'end':
num = 10
num = float(num.strip())
point_loads.append(num)
but it gave me the error: (plus it wouldn't have really have done what I wanted, but it was a start)
num = float(num.strip())
ValueError: could not convert string to float: 'end'
When debugging, I can see that I need to strip the string so that it doesnt preform an operation on ' end'.
I've tried messing around with different bits of code for a few hours now, but have made no progress.
Any tips for this part?
Thank you!

I'm not sure. But it might what you want?
for line in open("Input.txt"):
li = line.strip()
if li.startswith("point_load"):
l = li.split(', ')
for num in l[1:]:
if num == 'end':
num = '10'
num = float(num.strip())
point_loads.append(num)
l = li.split(',') turns to l = li.split(', '), use both , and to split string to list
num = 10 turns to num = '10' make all elements are string to call strip()

If I understand your problem, you are unable to exchange the string 'end' with a variable of your choosing. Based on what you've said, it's because you are not matching strings correctly first. When you split the line by comma, you are still getting whitespace for each item.
'point_loads, end, 300'.split() ends up as `['point_loads', ' end', ' 300']
In order to fix this I would first filter your lines to strip all whitespace from each item after the split. Then when you test if num == 'end' you will get True. Your current code is testing if 'end' == ' end' which is False.
point_loads = []
with open(path, 'r') as f:
for line in f:
li = line.strip()
if li.startswith("point_load"):
l = li.split(',')
l = [x.strip() for x in l] # strip whitespace from each item
for num in l[1:]:
if num == 'end':
num = 10.
else:
num = float(num.strip())
point_loads.append(num)
I noticed the second part of your problem has to do with the nature of Python and duck typing. You are trying to call a string method strip() on ints and strings. In my above code if it matches your string it assigns an int otherwise it will convert the string to an int thus avoiding the issue of trying to call strip on an int.
EDIT I fixed the code - I had made a typo and used split() instead of strip() in the list comprehension. I tested this in python3.6 but it should also work in python2.7. I added a proper context manager for opening the file too which you should always do.

Related

Reading an array from stdin using input() function throws an EOF error

Basically, I wish to sum the elements of the array provided in stdin. Why is it saying that list index is out of range? Is there anything special about the python input() function?
length = int(input())
li = []
for i in range(0, length):
li[i] = int(input())
sum = 0
for item in li:
sum = sum + item
Input
first line : length of array
second line : elements of the array.
EDIT : second line is a single string, not space separated integers.
3
1 2 3
Output:
Traceback (most recent call last):
File "./prog.py", line 6, in <module>
IndexError: list assignment index out of range
your question pretty much got answered, I just wanna show you a couple of tricks to make your program more simple and pythonic.
Instead of the for-loop try:
li = [int(i) for i in input().split(" ")]
And instead of the way you're calculating sum, try:
sum(li)
or even better:
sumOfItems = sum(int(i) for i in input().split(" "))
The thing with python lists is that you cannot assign a particular value to a position when that position originally does not exist, that is, the length of the list is less than the position that you want to change.
What you are trying to do is assign the value to a particular position in the list (called index) but since the list is empty, it's length is 0 and hence the index is out of range( that is it is not available for modifiying. That is why python is raising Index out of range error.
What you can try is:
l=[]
length=int(input())
for i in length:
l.append(int(input())
sum=0
for num in l:
sum=sum+num
You can solve this in a single line without even taking in the length. But you have to enter space separated values in a single line:
s = 0
for item in list(map(int, input ().split())):
s += item
If you want to input one integer per line, then you'll need the length(or a sentinel value):
s = 0
len = int(input())
li = [int(input ()) for _ in range(len)]
for item in li:
s = s + item
The second line of input turned out to be a single string and not space separated integers.
So I had to split the string, then convert the strings to integers to calculate their sum. Some of the methods mentioned above didn't work.
The list comprehension method will work in the space separated case, and is perfectly fine.
length = int(input())
l = input().split() # List of strings of integers.
S = 0
for item in l:
S += int(item) # Converting string to int
print(S)
You can't assign values to locations of a list that doesn't exist
try this:
length = int(input())
li = list(range(length))
for i in range(0, length):
li[i] = int(input())
sum = 0
for item in li:
sum = sum + item
you can also do something like this:
length = int(input())
li = []
for i in range(0, length):
li.append(int(input()))
total = sum(li)
print(total)

Error: invalid literal for int() with base 10: ' '

How to read the file with the numbers and save it in the list?
I tried this way but i got the error: ValueError: invalid literal for int() with base 10: ''
I would be grateful for your help and apologize for the grammar mistake.
The code:
file = open("edges.txt", "r")
list1 = []
for x in file.readlines():
list1.append([int(k) for k in x.rstrip("\n").split(" ")])
The content of my txt. file is:
1 2
3 5
2 4
4 6
It should look like:
[1, 2]
[3, 5]
[2, 4]
[4, 6]
Let's break it down, this:
list1.append([int(k) for k in x.rstrip("\n").split(" ")])
Is the equivalent of this:
list1 = []
for k in x.rstrip("\n").split(" "):
list1.append(int(k))
As you can see, k is clearly a part of a string, and the error means that it isn't a number. Try this:
file = open("edges.txt", "r")
list1 = []
for x in file.readlines():
list1.append([int(k) for k in x.rstrip("\n").split(" ") if k.isdigit()])
But in better practice:
with open("edges.txt", "r") as file:
list1 = []
for x in file.readlines():
list1.append([int(k) for k in x.rstrip("\n").split(" ") if k.isdigit()])
Use isalnum() since you are trying to convert to an integrer
You can use isdigit() of a string to validate that you are trying to convert number to int and another strip() method will help in this case since it seems that one line containing a number with space before or after.
file = open("edges.txt", "r")
list1 = []
for x in file.readlines():
list1.append([int(k) for k in x.rstrip("\n").strip().split(" ") if k.isdigit()])

How to remove last comma from print(string, end=“, ”)

my output from a forloop is
string = ""
for x in something:
#some operation
string = x += string
print(string)
5
66
777
I use the below code to have them on the same line
print(string, end=", ")
and then I get
5, 66, 777,
I want the final result to be
5, 66, 777
How do I change the code print(string, end=", ") so that there is no , at the end
The above string is user input generated it can me just 1 or 2,3, 45, 98798, 45 etc
So far I have tried
print(string[:-1], end=", ") #result = , 6, 77,
print((string, end=", ")[:-1]) #SyntaxError: invalid syntax
print((string, end=", ").replace(", $", "")) #SyntaxError: invalid syntax
print(", ".join([str(x) for x in string])) # way off result 5
6, 6
7, 7, 7
print(string, end=", "[:-1]) #result 5,66,777,(I thought this will work but no change to result)
print(*string, sep=', ') #result 5
6, 6
7, 7, 7
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
user input
twenty five, four, nine
gets
25, 4, 9, #(that stupid comma in the end)
You could build a list of strings in your for loop and print afterword using join:
strings = []
for ...:
# some work to generate string
strings.append(sting)
print(', '.join(strings))
alternatively, if your something has a well-defined length (i.e you can len(something)), you can select the string terminator differently in the end case:
for i, x in enumerate(something):
#some operation to generate string
if i < len(something) - 1:
print(string, end=', ')
else:
print(string)
UPDATE based on real example code:
Taking this piece of your code:
value = input("")
string = ""
for unit_value in value.split(", "):
if unit_value.split(' ', 1)[0] == "negative":
neg_value = unit_value.split(' ', 1)[1]
string = "-" + str(challenge1(neg_value.lower()))
else:
string = str(challenge1(unit_value.lower()))
print(string, end=", ")
and following the first suggestion above, I get:
value = input("")
string = ""
strings = []
for unit_value in value.split(", "):
if unit_value.split(' ', 1)[0] == "negative":
neg_value = unit_value.split(' ', 1)[1]
string = "-" + str(challenge1(neg_value.lower()))
else:
string = str(challenge1(unit_value.lower()))
strings.append(string)
print(', '.join(strings))
If you can first construct a list of strings, you can then use sequence unpacking within print and use sep instead of end:
strings = ['5', '66', '777']
print(*strings, sep=', ')
5, 66, 777
In case your for loop is doing also something else than printing, then you can maintain your current structure with this approach.
strings = ['5', '66', '777']
for i in range(len(strings)-1):
# some operation
print(strings[i], end=', ')
# some operation (last time)
print(strings[-1])
5, 66, 777
see I have solved this to print 1 to 5
Previously:
i = 1
while i<=5:
print(i, end=",")
i=i+1
Output:==> 1,2,3,4,5,
Now
lst=[]
i=1
while i<=5:
lst.append(str(i))
i=i+1
print(', '.join(lst))
Output:==> 1,2,3,4,5
I can suggest you to use a if-condition inside a for-loop like below
x=['1','2','3','4','5'] #Driver List
for i in range(0,len(x),1): #This loop iterates through the driver list
if( i==len(x)-1 ): #This checks whether i reached the last positon in iteration
print(i) #If i is in the last position, just print the value of i
else:
print(i,end=" , ") #If i is not in the last position, print the value of i followed by a comma
The output for this code is:
0 , 1 , 2 , 3 , 4 #Notice that no comma is printed in the last position
If text formatting is a concern, the simplest approach is to remove the last comma as shown in this example:
letters = ["a", "b", "c", "d", "e", "f"]
for i in letters:
print(f"{i}".upper(), end=", ") # some text formatting applied
print("\b\b ") # This removes the last comma.
Otherwise,
print (*letters, sep=", ")
works pretty well.
for i in range(10):
if(i==9):
print(i)
else:
print(str(i),end=",")
output : 0,1,2,3,4,5,6,7,8,9
list_name = [5, 10, 15, 20]
new_list = []
[new_list.append(f'({i}*{i+5})') for i in list_name]
print(*new_list,sep="+")
Output: (5*10)+(10*15)+(15*20)+(20*25)
for i in range(1,10):
print(i, end="+")
print("10")
Output:
1+2+3+4+5+6+7+8+9+10
in the end no + sign.

How to input a list in Python?

Usually, we input() a list in Python 3.X like this:
x = list(map(int, input()))
print (x)
But here let's say we give an input of 1234 then it prints:`
[1, 2, 3, 4]
Is there a way that I can print it like:
[12, 34]
Thanks in Advance!
Let's say you want the numbers to be entered separated by spaces. First get the entire line as input:
line = input()
Now parse the input. In this case, split on spaces:
words = line.split(' ')
Finally, convert each "word" to an int:
numbers = [int(i) for i in words]
Of course you can use map() instead of a list comprehension.
Note that this requires input such as
12 34
You can do this all in one line, but it is better to use variables to store each intermediate step. When you get it wrong, you can debug much more easily this way.
In my opinion, I would not complicate things :
I would declare an empty list :
l = []
Then I would simply append the input :
for i in range(0, n):
print("l[", i, "] : ")
p = int(input())
l.append(p)
You can notice here the "n",it's the size for the list,in your case it would be:
for i in range(0, 1):
print("l[", i, "] : ")
p = int(input())
l.append(p)
We always start from 0,so range(0,1) would count 0, then 1 and so on with other cases.
Hope this would help.

Python: reading integers in a file and adding them to a list

I am trying to create a function that takes an open file as an argument, reads the integers in the file which are all on their own line, then creates a list of those integers. The function should stop reading the file when there is an empty line. This is what I am stuck on.
def load_ints(file):
lst = []
x = 1
while x == 1:
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst = lst + load
else:
x = 2
x = 2
return lst
the file I am testing it with looks like this:
1
0
-12
53
1078
Should not be read by load_ints!
len(line.strip()) != 0:
is not working,
it currently gives me a ValueError: invalid literal for int() with base 10: 'Should'
You need to put a break after the x = 2
else:
x = 2
break
Otherwise, the for loop will keep iterating over the file. It has read the blank line, executed the else condition, then carried on processing lines. So it tries to process the 'Should...' line, and fails because 'Should...' is not an integer.
Also, I don't see why you have the while statement. The for loop should be enough to iterate over the file and process each line, and the break I've suggested will exit the loop when you hit the blank line.
Other answers already point out the issue: you have to stop parsing the integers when encoutering the blank line.
Here's a one-liner using itertools.takewhile, stopping when stripping the line yields an empty line & converting to integer:
import itertools
def load_ints(file):
return [int(x) for x in itertools.takewhile(str.strip,file)]
result:
[1, 0, -12, 53, 1078]
So itertools.takewhile iterates on the file lines, and applies strip on each line. If the result is an empty string, it stops the iteration. Otherwise it continues so the line is converted to integer and added to the list comprehension.
The less lines you're writing in those cases, the less bugs you'll create with auxiliary variables & states.
I think it is not necessary the while.
def load_ints(file):
lst = []
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst.append(load)
else:
break
return lst
When you read a file you get a generator. Instead of reading it all to memory we could use the while loop to feed us with 1 row at a time and break when condition is met (row is blank). This should be the most efficient solution.
data = """\
1
2
-10
1241
Empty line above"""
with open("test.txt","w") as f:
f.write(data)
with open("test.txt") as f:
data = []
while True:
row = next(f).strip()
try:
data.append(int(row))
# Break if ValueError is raised (for instance blank line or string)
except ValueError:
break
data
Returns:
[1, 2, -10, 1241]
If you want a compact solution we could use takewhile from itertools. But this won't handle any error.
from itertools import takewhile
with open("test.txt") as f:
data = list(map(int,takewhile(lambda x: x.strip(), f)))
If you want to stop reading the file when the line is empty, you have to break the for loop :
def load_ints(file):
lst = []
for line in file:
if len(line.strip()) != 0:
load = line.split()
load = [int(i) for i in load]
lst = lst + load
else:
break
return lst
You can also use re module:
import re
def load_ints(my_file):
return list(map(int, re.findall('-?\d', my_file.read())))

Categories

Resources