Reputation: 141
I am trying to get the sum of certain numbers from a file without changing the file itself
1 #person number
Marlon Holmes #Name
18.86 # First number
13.02 # Second Number
13.36 # Third Number
For the sum of numbers, it needs to be the #First, #second and #third number
The numbers currently are in cm which have been converted to inches which the two decimal places are necessary for
My code at present is to provide the top 3 people based on the sum of the #first,#second and #third numbers.
Current code:
data = []
names = OrderedDict([('Competitor Number', int),
('Competitor Name', str),
('Cucumber', to_inch),
('Carrot', to_inch),
('Runner Bean', to_inch)])
with open('veggies_2016.txt') as fobj:
while True:
item = {}
try:
for name, func in names.items():
item[name] = func(next(fobj).strip())
data.append(item)
except StopIteration:
break
sorted_data = sorted(data, key=itemgetter('Runner Bean'), reverse = True)
for entry in sorted_data[:3]:
for key, value in entry.items():
print value
print
There are about 50 records in the file that im reading from, which the sum must be added up for all then put in order to find the top 3 and ideally in two decimal places
Code referring to to_inch:
def to_inch(cm):
return float(cm) / 2.54
The whole document works around a main menu
To get the sum, I have tried sum(item.entry.items())
but with no success and have also tried "%.2f"
for the decimal figures/significant figures but with no success, any help would be appreciated
Upvotes: 2
Views: 4068
Reputation: 2304
If we disregard reading from the file for now and assume we can put the numbers in a list
we can use Python's round()
, sum()
, and map()
.
Code:
numbers = [18.86, 13.02, 13.36]
def to_inch(cm):
return cm/2.54
numbers_in_inches = list(map(to_inch, numbers))
print(numbers_in_inches)
numbers_rounded = list(map(round, numbers_in_inches, [0 for _ in numbers]))
print(numbers_rounded)
sum_numbers = sum(numbers_rounded)
print(sum_numbers)
Output:
[7.4251968503937, 5.125984251968504, 5.259842519685039]
[7.0, 5.0, 5.0]
17.0
What is happening:
to_inch
on each of the items in the list numbers
round()
function onto each the values in numbers_in_inches
, the reasoning for the list comprehension on the end is it creates a list of 0
's for map()
to use for round(number, places)
's places
.sum()
to take the sum of all of the numbers, of course, you can just use round(sum_numbers, 0)
if you want to round after the sum. Note: If you want to round after you sum, use math.fsum
instead of sum
as mentioned by Copperfield in the comments.Now to parse the file:
import re
numbers_names = {}
numbers = []
player_number = ''
name = ''
with open('file.txt', 'r') as f:
for line in f:
if '#person number' in line:
player_number = int(line.split('#')[0])
elif '#Name' in line:
name = line.split('#')[0]
else:
line_numbers = re.sub(r"[^\d.]", "", line)
if '.' in line_numbers:
numbers.append(float(line_numbers))
if len(numbers) >= 3 and player_number and name:
numbers_names.update({'player_number': player_number, 'name': name, 'numbers': numbers})
numbers, player_number, name = [], 0, ''
print(numbers_names)
Output:
{'name': 'Marlon Holmes ', 'numbers': [18.86, 13.02, 13.36], 'player_number': 1}
How It's parsing the file:
For each line in the file, it sees whether it's a line containing the player's name, the players number, or the numbers that he has.
Player Number Splits line into the note and the data then takes the data and sets it equal to player_number
.
Name Splits line into the note and the data then takes the data and sets it equal to name
.
in the file using re
's re.sub()
. Then, checks to see if there is a decimal in the cleaned-up line. Finally, if so it appends the line to numbers
.If all three values are present, it appends them all to the numbers_names
dictionary and resets the variables for the next player.
Upvotes: 3