Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to go from iterative approach to recursive approach

I have an iterative C# loop which fills out a checkboard pattern of up to 5 columns.

The values are paired, it's always a Headline and multiple Values for each column, and it's combining the values to a non-repetitative combination.

Starting with the simplest solution I could imagine, and after looking at it, I thought there must be a better approach to this problem by doing this recursively.

Below is an example of what I've tried so far:

 List<EtOfferVariant> variants = new List<EtOfferVariant>();

 _containers[0].Variant.ForEach(first =>
 {
     if (_containers.Count > 1)
     {
         _containers[1].Variant.ForEach(second =>
         {
             if (_containers.Count > 2)
             {
                 _containers[2].Variant.ForEach(third =>
                     {
                         EtOfferVariant va = new EtOfferVariant();
                         va.OfferVariant1Type = _containers[0].VariantKey;
                         va.OfferVariant1 = first;
                         va.OfferVariant2Type = _containers[1].VariantKey;
                         va.OfferVariant2 = second;
                         va.OfferVariant3Type = third;
                         va.OfferVariant3 = _containers[3].VariantKey;
                         variants.Add(va);
                     });
             }
             else
             {
                 EtOfferVariant va = new EtOfferVariant();
                 va.OfferVariant1Type = _containers[0].VariantKey;
                 va.OfferVariant1 = first;
                 va.OfferVariant2Type = second;
                 va.OfferVariant2 = _containers[1].VariantKey;
                 variants.Add(va);
             }
         });
     }
     else
     {
         EtOfferVariant va = new EtOfferVariant();
         va.OfferVariant1Type = _containers[0].VariantKey;
         va.OfferVariant1 = first;
         variants.Add(va);
     }
 });

The containers consist of a list of strings (the values) and a key (the headline).

It's a shortend version OfferVariant counts up to 5 in the real example.

I cant change the inital checkboard structure since its given by a existing database.

Below is an illustration of the data input and output for 2 containers consisting of:

Container 1:

  • Key: Pie
  • Values:
    1. Raspberry
    2. Strawberry

Container 2:

  • Key: Drink
  • Values:
    1. Cola,
    2. Coffee

The generated output would consist of 4 rows containing

edit due the fact its easyly missunderstood as its illustrated here

The Result will be a Row in a Database consisting of 4 columns

Column 1 | Column 2  | Column 3 | Column 4
Pie      | Raspberry | Drink    | Cola 
Pie      | Raspberry | Drink    | Coffee
Pie      | Strawberry| Drink    | Cola 
Pie      | Strawberry| Drink    | Coffee

EtOfferVariant is a ORM Poco containing those columns

like image 459
subkonstrukt Avatar asked Aug 20 '14 09:08

subkonstrukt


1 Answers

Thank you for your replies, Martin Liversage kinda guided me mental to it, tough it wasnt a pure cartesian product due the fact is was grouped to be flattend out latter and Cines approach gave me the final point in the right direction I solved this the following way now

in the first step I generate the inital rows for the first variant

    List<EtOfferVariant> row = new List<EtOfferVariant>();
    _containers.First().Variant.ForEach(o =>
    {
        row.Add(new EtOfferVariant() { OfferVariant1 = o, OfferVariant1Type = _containers.First().VariantKey });
    });
  return BuildVariants(row);

and then run it trough

  private List<EtOfferVariant> BuildVariants(List<EtOfferVariant> row, int containerIndex = 1)
    {
        List<EtOfferVariant> final = new List<EtOfferVariant>();
        row.ForEach(y =>
        {
            for (int i = 0; i < _containers[containerIndex].Variant.Count; i++)
            {
                var ret = MultiplyFromPrevious(y);
                FillByIndex(ret, _containers[containerIndex].Index, _containers[containerIndex].VariantKey, _containers[containerIndex].Variant[i]);
                final.Add(ret);
            }
        });
        containerIndex++;
        if (containerIndex < _containers.Count)
           return BuildVariants(final, containerIndex);
        return final;
    }

and thanks again to Cine

private EtOfferVariant MultiplyFromPrevious(EtOfferVariant variant)
{
    EtOfferVariant ret = new EtOfferVariant();
    ret.OfferVariant1 = variant.OfferVariant1;
    ret.OfferVariant2 = variant.OfferVariant2;
    ret.OfferVariant3 = variant.OfferVariant3;
    ret.OfferVariant4 = variant.OfferVariant4;
    ret.OfferVariant5 = variant.OfferVariant5;

    ret.OfferVariant1Type = variant.OfferVariant1Type;
    ret.OfferVariant2Type = variant.OfferVariant2Type;
    ret.OfferVariant3Type = variant.OfferVariant3Type;
    ret.OfferVariant4Type = variant.OfferVariant4Type;
    ret.OfferVariant5Type = variant.OfferVariant5Type;

    return ret;
}

I also seperated the column split into an own method, but it does nothing less then taking the index and map the values to the object, nothing special

thanks again everyone, this really loosend up the code

like image 144
subkonstrukt Avatar answered Sep 20 '22 16:09

subkonstrukt