-1

I started working on python and I'm currently stuck on this concept, and its kind of hard to explain so I'll use an example.

Example:

I have a txt file containing: France,210026,63929000,1.15

I have already figured out how to split the elements and add them to the list. But I want to add the numbers as floats and the country name as a string.

Currently what I do is:

inf = []
with open('small.txt', 'r') as inputFile:
    for line in inputFile:
        line = line.strip()
        if line != '':
            info += line.split(',')
print info

the output is:

['France', '210026' , '63929000', '1.15']

As you can see this is a list of strings. Want I actually want is for only France to be the string, the rest should be floats. Any ideas?

Thanks

Gawndy
  • 51
  • 1
  • 11

4 Answers4

2

If you mostly expect all lines in the input in the same format, you can try read them in that format, perhaps taking care of the eventually misformed lines

info = []
with open('small.txt', 'r') as inputFile:
    for line in inputFile:
        line = line.strip()
        if line != '':
            try:
                (a,b,c,d) = [ll.strip() for ll in line.split(',')] 
                info.append([a, int(b), int(c), float(d)])
            except IOError as (errno, strerror):
                print "I/O error %s: %s" % (errno, strerror)
            except ValueError:
                print "Malformed line:" + line
            except:
                print "Unexpected error:", sys.exc_info()[0]
                raise
Ashalynd
  • 12,363
  • 2
  • 34
  • 37
  • You should never use blanket except statements. It would be much better to write except ValueError in this case. – mdadm Apr 10 '14 at 22:36
  • good point, changed the try/except block – Ashalynd Apr 10 '14 at 23:28
  • getting better... you still shouldn't use the blanket except. If you are looking for a catch-all try except [StandardError](https://docs.python.org/2/library/exceptions.html#exceptions.StandardError) instead, otherwise you'll catch KeyboardInterrupt, SystemExit, etc. Fix that and I'll remove my down vote :) – mdadm Apr 10 '14 at 23:36
1

There are a couple of options here, one option would be to just try to convert every element to a float and handle any exceptions to leave non-float values as strings:

info = []
with open('small.txt', 'r') as inputFile:
    for line in inputFile:
        line = line.strip()
        if line != '':
            fields = line.split(',')
            for i, x in enumerate(fields):
                try:
                    fields[i] = float(x)
                except ValueError:
                    pass
            info += fields
print info

Or alternatively, if you are confident in the format of the file you can just convert starting at index 1 (after the country):

info = []
with open('small.txt', 'r') as inputFile:
    for line in inputFile:
        line = line.strip()
        if line != '':
            fields = line.split(',')
            fields[1:] = map(float, fields[1:])
            info += fields
print info

As a side note, are you sure you want to do info += ... instead of info.append(...)? The difference here is that with += you will have a flat list, and with using append the data from each line will be in its own inner list (for example [['France', 1.0, 2.0, 3.0], ['England', 4.0, 5.0, 6.0]]).

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • yes, indeed, append adds the list (or tuple) from the given line as one element, whereas += would expand the original list. – Ashalynd Apr 10 '14 at 22:15
0
data = []
with open('small.txt','r') as inputFile:
    for line in inputFile:
        line = line.strip()
        if not line: continue # if the line is empty, skip the rest
        info = []
        for element in line.split(","):
            try:
                info.append(float(element))
            except ValueError:
                info.append(element)
        data.append(info)

This will try to convert every element to a float (that is, a number with a fractional part like 1.15). If float(element) fails (as it will with "France", since "France" is clearly not a number), it will throw a ValueError so we catch it and just use the string instead.

Adam Smith
  • 52,157
  • 12
  • 73
  • 112
0

I'm going to suggest that you define a function to try and convert a value to a float, then call map on the results of split. This might be a bit cleaner then the other solutions proposed so far.

def to_float(value):
    try:
        return float(value)
    except ValueError:
        return value

with open('small.txt') as data_file:
    for row in data_file:
        fields = map(to_float, row.strip().split(','))
        print fields

An alternative solution would be to use the csv module, and let it take care of the conversion for you. This of course requires that everything in the CSV file that is a string, be in quotes. If you can get the file in that format, great. You can accomplish this by passing quoting=csv.QUOTE_NONNUMERIC to the constructor of reader.

import csv

with open('small.txt') as data_file:
    csv_reader = csv.reader(data_file, delimiter='\t',
                            quoting=csv.QUOTE_NONNUMERIC)

    for row in csv_reader:
        print row #results will be floats if not quoted
mdadm
  • 1,333
  • 1
  • 12
  • 9