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.


Reply via email to