-2

I have a list of employees with days. I am using C# to generate running numbers in the days column as shown in the image below. I have tried the solution in this link and was able to generate a dense rank for each group. I am not able to generate a running number for the rest of the items in the list.

Desired result:

Desired result

Grant Winney
  • 65,241
  • 13
  • 115
  • 165
  • 1
    What does the input list look like. It looks like you are creating a pivot table. So first step is to get the max number of days. Then create a table with the number of columns 3 (empnumber, empName, Number of days) + max number of days. Then fill in table. So if you have max number of days = 10 the number of columns is 13. – jdweng Sep 05 '19 at 18:55
  • What data type do you expect the result to use? – NetMage Sep 05 '19 at 21:55

1 Answers1

1

Since I like LINQ :)

Using my simplest implementation of the APL Scan operator for IEnumerable (which is like Aggregate but returns the intermediate results):

public static class IEnumerableExt {
    // Explicit seed value
    // TRes combineFn(TRes PrevResult, T CurValue)
    public static IEnumerable<TRes> Scan<T, TRes>(this IEnumerable<T> src, TRes seed, Func<TRes, T, TRes> combineFn) {
        foreach (var s in src) {
            seed = combineFn(seed, s);
            yield return seed;
        }
    }    
}

And a simple class the increments each time it is read:

public class GeneratorInt {
    int curValue = 1;

    public int Value {
        get {
            return curValue++;
        }
    }
}

You can compute the answer (using null for the empty boxes):

var ans = src.Scan(new {
                        EmpNumber = 0,
                        EmpName = "",
                        NumberOfDays = 0,
                        Days1 = (GeneratorInt)null,
                        Days2 = (GeneratorInt)null,
                        Days3 = (GeneratorInt)null,
                        Days4 = (GeneratorInt)null,
                        Days5 = (GeneratorInt)null
                   },
                   (acc, r) => new {
                        r.EmpNumber,
                        r.EmpName,
                        r.NumberOfDays,
                        Days1 = r.NumberOfDays >= 1 ? (acc.Days1 ?? new GeneratorInt()) : null,
                        Days2 = r.NumberOfDays >= 2 ? (acc.Days2 ?? new GeneratorInt()) : null,
                        Days3 = r.NumberOfDays >= 3 ? (acc.Days3 ?? new GeneratorInt()) : null,
                        Days4 = r.NumberOfDays >= 4 ? (acc.Days4 ?? new GeneratorInt()) : null,
                        Days5 = r.NumberOfDays >= 5 ? (acc.Days5 ?? new GeneratorInt()) : null,
                   }
             )
             .Select(a => new {
                a.EmpNumber,
                a.EmpName,
                a.NumberOfDays,
                Days1 = a.Days1?.Value,
                Days2 = a.Days2?.Value,
                Days3 = a.Days3?.Value,
                Days4 = a.Days4?.Value,
                Days5 = a.Days5?.Value,
             })
             .ToList();

If you need to handle differing potential number of Days# fields, then you have to decide how you want to handle them - using one field of type List<int> or of type IEnumerable<int>, or using a DataTable and create columns dynamically?

NetMage
  • 26,163
  • 3
  • 34
  • 55