Sat Dec 07, 2019 4:13 am
Login Register Lost Password? Contact Us


Constructing records from combinations of text fragments.

Questions around writing code and queries

Thu Nov 28, 2019 1:37 pm Change Time Zone

Hi,

I expect this is posted else where as this seems a straightforward question, but given a variable number of text fragments (with a known final position in the record) how does one generate all records for every combination?
Example
Code: Select all
Field Position     Text
1                  Allan
1                  Nina
2                  5
2                  6
2                  7
3                  ABC


Produces 6 records:

Code: Select all
Allan,5,ABC
Allan,6,ABC
Allan,7,ABC
Nina,5,ABC
Nina,6,ABC
Nina,7,ABC

The number of fields is also variable

In languages that allow recursion this is straightforward, but in ECL one can't reference a function from within itself. I've investigated LOOP but drawn a blank.
(Hum something like LOOP where the input record structure holds both the input child datasets AND the resultant string, slowly adding to the output and removing records from the child datasets until all child datasets are all empty????)

Thanks in advance

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

Fri Nov 29, 2019 3:08 pm Change Time Zone

An elegant solution from Tony Kirk,
One has to remember that the next iteration to LOOP holds what’s constructed in the previous iteration, |Tony's also incremented the field number it's joining on as you go along.
Code: Select all
rIn  :=
record
  unsigned2  FieldPos;
  string     TextValue;
end;
dIn  := dataset([{1, 'Allan'},
                 {1, 'Nina'},
                 {2, '5'},
                 {2, '6'},
                 {2, '7'},
                 {3, 'ABC'},
                 {3, 'DEF'},  // Added these
                 {4, '1A'},
                 {4, '2B'}
                ], rIn
               );

//----------------------------------------------
rIn  tJoin(rIn pLeft, rIn pRight) :=
transform
  self.FieldPos  :=  pRight.FieldPos;  // Sets up for next JOIN
  self.TextValue :=  trim(pLeft.TextValue) + if(pRight.FieldPos <> 0, ',' + trim(pRight.TextValue), '');  // both TRIMs probably redundant
end;
fJoin(dataset(rIn) pStartDataset, unsigned2 pLeftFieldPos) := join(pStartDataset, dIn,
                                                                   left.FieldPos = pLeftFieldPos and right.FieldPos = left.FieldPos + 1,
                                                                   tJoin(left, right)
                                                                  );

// REQUIRES FieldPos values start with 1 and have no gaps (didn't test what happens if 1 only).  Otherwise,
//   it would require prep to align low value with 1 and each subsequent iterated value one higher and use *that* MAX.
lLoopCount :=  max(dIn, FieldPos) - 1;
dLoop      :=  loop(dIn, lLoopCount, fJoin(rows(left), counter)); // Form 1 of LOOP
//----------------------------------------------

output(dLoop);


Nice one Tony
Allan
 
Posts: 386
Joined: Sat Oct 01, 2011 7:26 pm


Return to Programming

Who is online

Users browsing this forum: MSN [Bot] and 1 guest

cron