Search code examples
c#listgroup-by.net-2.0ienumerable

Trying GroupBy within List in c#


In the below case, I want to get a count of how many times the employee is repeating. For example, if the list has EmpA 25 times, I would like to get it. I am trying with GroupBy but not getting results. I can do record skip and find the count but there are lot of records.

So in below example, lineEmpNrs is the list and I want to have grouping results by employee ID.

Please suggest.

public static string ReadLines(StreamReader input)
{
string line;
while ( (line = input.ReadLine()) != null)
   yield return line;

}

private taMibMsftEmpDetails BuildLine(string EmpId, string EmpName, String ExpnsDate)
{
taMibMsftEmpDetails empSlNr = new taMibMsftEmpDetails();
empSlNr.EmployeeId  = EmpId;
empSlNr.EmployeeName   = EmpName;
empSlNr.ExpenseDate = ExpnsDate;
return empSlNr;

}

List<taMibMsftEmpDetails> lineEmpNrs = new List<taMibMsftEmpDetails>();
foreach (string line in ReadLines(HeaderFile))
{ 
headerFields = line.Split(',');
lineEmpNrs.Add(BuildLine(headerFields[1],headerFields[2],headerFields[3]));
}

Solution

  • You can define following delegate, which you will use to select grouping key from list elements. It matches any method which accepts one argument and returns some value (key value):

    public delegate TResult Func<T, TResult>(T arg);
    

    And following generic method, which will convert any list to dictionary of grouped items

    public static Dictionary<TKey, List<T>> ToDictionary<T, TKey>(
        List<T> source, Func<T, TKey> keySelector)
    {
        Dictionary<TKey, List<T>> result = new Dictionary<TKey, List<T>>();
    
        foreach (T item in source)
        {
            TKey key = keySelector(item);
            if (!result.ContainsKey(key))
                result[key] = new List<T>();
            result[key].Add(item);
        }
    
        return result;
    }
    

    Now you will be able to group any list into dictionary by any property of list items:

    List<taMibMsftEmpDetails> lineEmpNrs = new List<taMibMsftEmpDetails>();
    // we are grouping by EmployeeId here
    Func<taMibMsftEmpDetails, int> keySelector = 
        delegate(taMibMsftEmpDetails emp) { return emp.EmployeeId; };
    
    Dictionary<int, List<taMibMsftEmpDetails>> groupedEmployees = 
        ToDictionary(lineEmpNrs, keySelector);