Sat Mar 23, 2019 12:20 pm
Login Register Lost Password? Contact Us


Dynamically create a record structure

Comments and questions related to the Enterprise Control Language

Thu Feb 21, 2019 9:15 pm Change Time Zone

Is there a way to dynamically create a record structure? For example if I have a dataset with a list of names I want to keep as one record. Something like:

Code: Select all
currRec := record
    unicode id;
    unicode name_list;
end;

ds := dataset([{'12345','[Smith|Will|J$Patel|Sandeep|R]'}],currRec);


I'd like to transform it to a single dataset like. The dataset could have 1-N of names in the list.

Code: Select all
export currRec := record
    unicode id;
    unicode last_1;
    unicode first_1;
    unicode middle_1;
    unicode last_2;
    unicode first_2;
    unicode middle_2;
end;

ds := dataset([{'12345','Smith','Will','J','Patel','Sandeep','R']'}],currRec);
wjblack
 
Posts: 17
Joined: Mon Jul 11, 2016 12:45 pm

Fri Feb 22, 2019 1:53 pm Change Time Zone

Hi WjBlack,

I'm sure this is possible, but can you clarify some things for progres to be made.

1. Is the input known (i.e. the list of names) known at compile time or runtime?
2. There is some defined structure to the input, like the names always gets presented in triplets of firstname,middlename and surname, without gaps? (i.e. there are place holders where parts of the name do not exist)
Yours
Allan
Allan
 
Posts: 351
Joined: Sat Oct 01, 2011 7:26 pm

Fri Feb 22, 2019 2:11 pm Change Time Zone

wjblack,

Rather than a dynamic RECORD structure, you might want to look at using a nested child dataset, like this:
Code: Select all
IMPORT Std;
currRec := RECORD
  UNICODE id;
  UNICODE name_list;
END;

ds := DATASET([{'12345','[Smith|Will|J$Patel|Sandeep|R]'},
               {'23456','[John|Joe|Sue$Smith|Deepak|Q]'}
              ],currRec);
Crec := {UNICODE name};
OutRec := RECORD
  UNICODE id;
  DATASET(Crec) Names;
END;

PROJECT(ds,TRANSFORM(OutRec,
                     JustNames := LEFT.name_list[2.. LENGTH(LEFT.name_list)-1];
                     SELF.Names := DATASET(Std.Uni.SplitWords(JustNames,'|'),Crec),
                     SELF := LEFT));

HTH,

Richard
rtaylor
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1431
Joined: Wed Oct 26, 2011 7:40 pm

Sat Feb 23, 2019 4:40 pm Change Time Zone

Thanks Richard. I went with the child dataset idea although I'm facing one other problem to display the tokens of the second child programmatically. I'm using STD.STr.SplitWords to split the child attribute values based on the ^SF^ delimiter. As it stands the values lastname, firstname, grade, gpa are duplicated for both children.

Code: Select all
IMPORT Std;

currRec := RECORD
  UNICODE id;
   UNICODE person_ct;
  UNICODE person_list;
END;

ds := DATASET([{'12345','2','Smith^SF^John^SF^100^SF^4.0^SF^Black^SF^Henry^SF^100^SF^3.8'}],currRec);

ChildRec := record             
  unsigned child_num;
  unicode lastname;
  unicode firstname;
  unicode grade;
  unicode gpa;
end;

ParentRec := RECORD
  UNICODE id;
  UNICODE person_ct;
  DATASET(ChildRec) Persons;
END;
                              
PROJECT(ds,TRANSFORM(ParentRec,
           JustNames := LEFT.person_list[1.. LENGTH(LEFT.person_list)];
           Tokens := STD.STr.SplitWords((string)JustNames,'^SF^');
           Child_ct := (unsigned)LEFT.person_ct;
           SELF.Persons := normalize(dataset([{JustNames}],{string str}),
                           Child_ct,                                                      
                                     TRANSFORM(ChildRec,
                                               self.child_num := counter;            
                                self.lastname := Tokens[1];                                                            
                                self.firstname := Tokens[2];                                                            
                                self.grade := Tokens[3];                                                            
                                self.gpa := Tokens[4];                                                            
                                SELF := LEFT)),                                                            
                     SELF := LEFT));
wjblack
 
Posts: 17
Joined: Mon Jul 11, 2016 12:45 pm

Mon Feb 25, 2019 9:35 am Change Time Zone

Hi wjblack,

The problem with your code is that your unconditionally index tokens by 1,2,3,4. You have to batch the strings up into groups of 4 elements.
See example code below. I've added a check to fail the WU if the input names are not multiples of 4 fields.

I don't make any pretence that this is a definitive solution, as I've just knocked it up, but it gives you an idea on how to progress.
Code: Select all
IMPORT STD;

currRec := RECORD
  UNSIGNED id;
  STRING person_list;
END;

ds := DATASET([{12345,'Smith^SF^John^SF^100^SF^4.0^SF^Black^SF^Henry^SF^100^SF^3.8'}
              ,{67890,'Jones^SF^Allan^SF^90^SF^5.0'}
              ,{22334,'Cooper^SF^Fran^SF^30^SF^1.0^SF^Fletcher^SF^Ian^SF^70^SF^3.8^SF^Johnson^SF^Boris^SF^20^SF^0.8'}],currRec);

ChildRec := record             
  unsigned child_num;
  unicode lastname;
  unicode firstname;
  unicode grade;
  unicode gpa;
end;

ParentRec := RECORD
  UNSIGNED id;
  DATASET(ChildRec) Persons;
END;

ParentRec ProcessOneInputRecord (currRec L) := TRANSFORM

    Children := STD.Str.SplitWords(L.person_List,'^SF^');
    CntChildren := IF(COUNT(Children) % 4 != 0,ERROR('missing children fields: '+(STRING)L.id),COUNT(Children) DIV 4);

    ChildRec GetOneChild({UNSIGNED dummy} L,UNSIGNED Cnt) := TRANSFORM
        UNSIGNED offset := Cnt*4-3;
        SELF.child_num  := Cnt;
        SELF.lastname   := Children[offset];
        SELF.firstname  := Children[offset+1];
        SELF.grade      := Children[offset+2];
        SELF.gpa        := Children[offset+3];
    END;

    SELF.Id := L.id;
    SELF.Persons := NORMALIZE(DATASET([{0}],{UNSIGNED dummy}),CntChildren,GetOneChild(LEFT,COUNTER));

END;
                             
PROJECT(ds,ProcessOneInputRecord(LEFT));

Yours
Allan
Allan
 
Posts: 351
Joined: Sat Oct 01, 2011 7:26 pm


Return to ECL

Who is online

Users browsing this forum: No registered users and 0 guests

cron