I have a file that looks like:
1 1 C C 1.9873 2.347 3.88776
1 2 C Si 4.887 9.009 1.21
I would like to read in the contents of the file, line-by-line. When I only had numbers on the lines I used:
for line in readlines(file):
data = map(float, line.split)
But this only works when all the elements of line.split are numbers. How can I make it store the letters as strings and the numbers as floats?
for line in infile:
data = [x if x.isalpha() else float(x) for x in line.split()]
There will be issues if your data contains fields that are neither alphabetic nor valid floating-point numbers (for example, "A1"). Your data doesn't seem to have these from what you said, but if it does, the try/except
approach suggested by Igor would probably suit better.
I would probably use a more generic function that can be given the types to try, however:
def tryconvert(value, *types):
for t in types:
try:
return t(value)
except (ValueError, TypeError):
continue
return value
for line in infile:
data = [tryconvert(x, int, float) for x in line.split()]
This will convert anything that be converted to an integer to an int
, failing that it will try float
, and then finally it just gives up and returns the original value, which we know will be a string. (If we didn't know it was a string we could just stick str
on the end of our call to tryconvert()
.)
$ cat 1.py
def float_or_str(x):
try:
return float(x)
except ValueError:
return x
line = '1 1 C C 1.9873 2.347 3.88776'
print map(float_or_str, line.split())
$python 1.py
[1.0, 1.0, 'C', 'C', 1.9873, 2.347, 3.88776]
You can use methods str.isalpha(), str.isalphanum(), str.isdigit to decide if your string is a number or not.