Search code examples
filefunctional-programmingd

How to count number of lines and perform operations in functional way in D?


I have the following piece of code:

import std.algorithm;
import std.array;
import std.csv;
import std.stdio;
import std.typecons;
import std.getopt;
import std.file;
import std.conv;

struct DataPoint{
    double x,y,z;

    this(double _x, double _y, double _z){
        x = _x;
        y = _y;
        z = _z;
    }

    this(char[][] a){
        x = to!double(a[0]);
        y = to!double(a[1]);
        z = to!double(a[2]);
    }

    DataPoint opBinary(string s)(DataPoint d) if (s == "+"){
        auto ret = DataPoint(x + d.x, y + d.y, z + d.z);
        return ret;
    }
}

void main(string[] args)
{
    string csvFile;
    try{
        getopt(args, std.getopt.config.required, "input|i", &csvFile);
        assert(csvFile.isFile);
    }
    catch(Exception e){
        writeln(e.msg);
        return;
    }

    auto file = File(csvFile, "r");
    int lineCount = 0;
    foreach (string line; lines(file)){
        ++lineCount;
    }
    file.close();

    file = File(csvFile, "r");
    auto aa = file.byLine()                      // Read lines
                       .map!split                // Split into words
                       .map!(a => DataPoint(a))
                       .reduce!((a,b) => a + b);
    auto average = DataPoint(aa.x/lineCount, aa.y/lineCount, aa.z/lineCount);

    std.stdio.writefln("After reading %d records, "
                      ~"the average is [%.2f, %.2f, %.2f]", lineCount, average.x, average.y, average.z);
}

How can I count the number of lines in the file while iterating over its contents at the same? (in one pass)


Solution

  • It's not very functional, but you can use tee for inline processing:

    int count = 0;
    auto x = stdin.byLine.tee!(_ => ++count).map!(/+ ... whatever ... +/);