On 03/18/2012 07:45 AM, bioinfornatics wrote:
> dear, i have this data:
> ________________________________
> data1      data2   data3a;data3b;data3c
> cata1      cata2   cata3a;cata3b;cata3c
> tata1      tata2   tata3a;tata3b;tata3c
> ________________________________
>
> field are sepaated by tab but third field contain data separeted by semi
> colon
>
> I have try:
> ________________________________
> import std.csv;
> import std.string;
> import std.stdio;
>
> struct Data{
>      public:
>          string field1;
>          string field2;
>
>      @property void field3( string field ){
>          _field3 = field.split(";");
>      }
>      @property string[] field3(  ){
>          return _field3;
>      }

Besides the confusion that Jesse Phillips has pointed out, csvReader cannot decide to treat those two property functions as if they represent a member of Data.

>
>      private:
>          string[] _field3;

Data still has three members: field1, field2, and _field3.

The problem is, although the format clearly states that there are three strings that are delimited by '\t', the third field of the struct is not a string.

> }
>
> void main(){
>      Data[] result;
>      File f = File( "data.csv", "r" );
>      foreach( char[] line; f.byLine() ){
>          result ~= csvReader!Data(line, '\t').front;
>      }
> }

So the solution is that _field3 must be a string:

import std.csv;
import std.string;
import std.stdio;

struct Data{
    public:
        string field1;
        string field2;

    private:
        string _field3;
}

void main(){
    Data[] result;
    File f = File( "data.csv", "r" );
    foreach( char[] line; f.byLine() ){
        result ~= csvReader!Data(line, '\t').front;
    }

    writeln(result);
}

You must provide the properties on top of that:

import std.csv;
import std.string;
import std.stdio;

struct Data{
    public:
        string field1;
        string field2;

    void field3( string[] field ) @property {
        _field3 = field.join();
    }

    string[] field3(  ) @property {
        return _field3.split(";");
    }

    string toString() {
        return format("%s,%s,%s", field1, field2, field3);
    }

    private:
        string _field3;
}

void main(){
    Data[] result;
    File f = File( "data.csv", "r" );
    foreach( char[] line; f.byLine() ){
        result ~= csvReader!Data(line, '\t').front;
    }

    writeln(result);
}

Note that to avoid confusing the readers, the property functions both use string[], not string. (I've also put @property at the end of the function signature, which I started to favor recently.)

The optimizations can come after that. The following calls split() only whene necessary:

import std.csv;
import std.string;
import std.stdio;

struct Data{
    public:
        string field1;
        string field2;

    void field3( string[] field ) @property {
        _field3 = field;
        _raw_field3 = null;
    }

    string[] field3(  ) @property {
        if (_raw_field3 !is null) {
            _field3 = _raw_field3.split(";");
        }
        return _field3;
    }

    string toString() {
        return format("%s,%s,%s", field1, field2, field3);
    }

    private:
        string _raw_field3;
        string[] _field3;
}

void main(){
    Data[] result;
    File f = File( "data.csv", "r" );
    foreach( char[] line; f.byLine() ){
        result ~= csvReader!Data(line, '\t').front;
    }

    writeln(result);
}

Ali

Reply via email to