code D'ish enough? - ignore previous post with same subject

Jordan Wilson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Feb 26 13:50:38 PST 2017


On Sunday, 26 February 2017 at 19:34:33 UTC, thorstein wrote:
> Hi,
>
> sorry for posting again, but I used a keyboard combination that 
> accidently send my post before it was done.
>
> Coming more or less from Python I just started with D. Not a 
> real programmer, just automating things and looking for a neat 
> compiled language.
>
> Just to learn, I wrote a function to read CSV-like files (I 
> know D has its own routine). Since I'm still a bit overwhelmed 
> by the many complex language features, I'm curious what could I 
> change to make my code as D'ish as possible?
>
> Thank you for any suggestion,
> Thorstein
>
> // Reads CSV-like files with only numeric values in each column
> // new_ndv replaces ndv, which is the original no-data-value
> double[][]* readNumMatCsv(char[] filePath, int numHeaderLines, 
> char[] ndv, char[] new_ndv)
> { double[][]* p_numArray;
>   double[][] numArray;
>   char[] line;
>   string noCont = "File content not usable. Quit here.";
>   string noFile = "Could not read file. Quit here.";
>   string nonNum = "Found a non-numeric value in data matrix. 
> Quit here.";
>   Regex!char re = regex(r"(\n$)");
>
>   if(exists(filePath))
>   { File f = File(filePath, "r");
>     if((line = f.readln().dup).length > 0)
>     { while (!f.eof())
>       // 1st replace ndv with new_ndv, 2nd remove all \n, 3rd 
> check id size of read line >0
>       { if((line = replaceAll(f.readln().dup.replace(ndv, 
> new_ndv), re, "")).length > 0)
>         // check if all elements of splitted line are numeric
>         { foreach(i;split(line,","))
>           { if(isNumeric(i) == false)
>             // otherwise return pointer to empty array
>             { writeln(nonNum);
>               return p_numArray;
>             }
>           }
>           // convert characters to double
>           if(split(line,",").length > 0)
>           { numArray ~= to!(double[])(split(line,","));
>           }
>         }
>       }
>       // pass reference to pointer
>       p_numArray = &numArray;
>       // first line empty -> return pointer to empty array
>     } else { writeln(noCont); }
>     // file could not be find
>   } else { writeln(noFile); }
>   return p_numArray;
> }

I'm in a similar boat, as I continue to learn D, I find myself 
using UFCS, "auto", and operating on ranges alot more; I think 
that's considered idiomatic.

For example, here is my rough attempt:
auto readNumMatCsv2 (string filePath, string ndv, string new_ndv){
     double[][] p_numArray;
     try {
         auto lines = File(filePath,"r").byLine;
         lines.popFront; // get read of header
         p_numArray = lines.map!(a => a.replace (ndv,new_ndv)
                                       .splitter (",")
                                       .map!(a => a.to!double)
                                       .array)
                           .array;
     } catch (Exception e){
         e.msg.writeln; // this replaces "Could not read file. 
Quit here."
     }
     return p_numArray;
}

It took me quite a while to get the whole usage of range stuff 
like "map" and "filter" etc., but I think it's worth the effort.




More information about the Digitalmars-d-learn mailing list