Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #45795

Re: file I/O and arithmetic calculation

References (2 earlier) <CAHVvXxR-5-s6GBY0nR_J--w=+T1SyeauCkEr_Frncj+trE=aWg@mail.gmail.com> <BLU176-W1629E4C46CA08C58AA583CD7A90@phx.gbl> <CAHVvXxRL=4+9+CkMKfZ3ei86i0xF14JZRpT2rB1RgmBV+ATtug@mail.gmail.com> <BLU176-W45829351ABC75D63C63DC9D7AA0@phx.gbl> <BLU176-W34475DEC9894A483FC75C0D7AA0@phx.gbl>
From Oscar Benjamin <oscar.j.benjamin@gmail.com>
Date 2013-05-23 11:37 +0100
Subject Re: file I/O and arithmetic calculation
Newsgroups comp.lang.python
Message-ID <mailman.2008.1369305461.3114.python-list@python.org> (permalink)

Show all headers | View raw


On 23 May 2013 04:15, Carlos Nepomuceno <carlosnepomuceno@outlook.com> wrote:
> The last line of my noob piece can be improved. So this is it:

Most of it can be improved.

> filenames = ['1.txt', '2.txt', '3.txt', '4.txt', '5.txt']
> contents  = [[[int(z) for z in y.split(',')] for y in open(x).read().split()] for x in filenames]
> s1c  = [sum([r[0] for r in f]) for f in contents]
> a1r  = [sum(f[0])/float(len(f[0])) for f in contents]
> print '\n'.join(['File "{}" has 1st row average = {:.2f}'.format(n,a1r[i]) for i,n in enumerate(filenames) if s1c[i]==50])

You're writing repeated list comprehensions that feed into one another
like this:

list2 = [func1(x) for x in list1]
list3 = [func2(y) for y in list2]
list4 = [func3(y) for y in list2]

In this case it is usually better to write a single loop

for x in list1:
    y = func1(x)
    v = func2(y)
    w = func3(y)

With that your code becomes:

filenames = ['1.txt', '2.txt', '3.txt', '4.txt', '5.txt']
for filename in filenames:
    contents  = [[int(z) for z in y.split(',')] for y in
open(filename).read().split()]
    s1c  = sum([r[0] for r in contents])
    a1r  = sum(f[0])/float(len(contents[0]))
    if s1c == 50:
        print('File "{}" has 1st row average = {:.2f}'.format(filename,a1r))

However you shouldn't really be doing open(x).read().split() part. You
should use the with statement to open the files:

with open(filename, 'rb') as inputfile:
    contents = [map(int, line.split()) for line in inputfile]

Of course if you don't have so many list comprehensions in your code
then your lines will be shorter and you won't feel so much pressure to
use such short variable names. It's also better to define a mean
function as it makes it clearer to read:

# Needed by the mean() function in Python 2.x
from  __future__ import division

def mean(numbers):
    return sum(numbers) / len(numbers)

filenames = ['1.txt', '2.txt', '3.txt', '4.txt', '5.txt']

for filename in filenames:
    with open(filename, 'rb') as inputfile:
        matrix = [map(int, line.split()) for line in inputfile]
    column1 = [row[0] for row in matrix]
    row1 = matrix[0]
    if mean(column1) == 50:
        print('File "{}" has 1st row average =
{:.2f}'.format(filename, mean(row1)))

It's all a little easier if you use numpy:

import numpy as np

filenames = ['1.txt', '2.txt', '3.txt', '4.txt', '5.txt']

for filename in filenames:
    matrix = np.loadtxt(filename, dtype=int)
    column1 = matrix[:, 0]
    row1 = matrix[0, :]
    if sum(column1) == 50 * len(column1):
        print('File "{}" has 1st row average =
{:.2f}'.format(filename, np.mean(row1)))

Then again in practise I wouldn't be testing for equality of the mean.


Oscar

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: file I/O and arithmetic calculation Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-05-23 11:37 +0100

csiph-web