-1

I have the following Customer class:

public class Customer
{
    public string Name  {get; set;}
    public string Email {get; set;}
    public string City  {get; set;}
}

Customer Collection

List<Customer> customers = //assigned range of customers

Now I need to group by all fields. I don't want to select individual fields. In my actual scenario, it runs more dynamic, so I cannot predefine the fields.

From this customers object I need to construct a matrix like

Name |   Email    | City | count
AB     ef@g.com     ss      3
CB      f@g.com     ss      2
EF      k@s.com     ss      34
ek      g.com       we      84

I tried going this route. Extension method to group by multiple columns

public static IEnumerable<GroupResult> GroupByMany<TElement>(
    this IEnumerable<TElement> elements, List<string> groupSelectors)
{
    var selectors =
        new List<Func<TElement, object>>(groupSelectors.Count);
    foreach (var selector in groupSelectors)
    {
        LambdaExpression lambdaExpression =
            System.Linq.Dynamic.DynamicExpression.ParseLambda(typeof(TElement), typeof(object), $"it[\"{selector}\"]");
        selectors.Add((Func<TElement, object>) lambdaExpression.Compile());
    }
    return elements.GroupByMany(selectors.ToArray());
}

and call it like

customers.GroupByMany(displayFields);

Problem is I am getting the results as nested groups

public class GroupResult
{
    public object Key { get; set; }
    public int Count { get; set; }
    public IEnumerable Items { get; set; }
    public IEnumerable<GroupResult> SubGroups { get; set; }
    public override string ToString()
    {
        return $"{Key} ({Count})";
    }
}

That is going away from what I need again.

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
HaBo
  • 13,999
  • 36
  • 114
  • 206

1 Answers1

1

To group by the entire object and count occurrences (or in other words "count duplicates") just group by the iterated item like this:

var result = from item in customers
             group 1 by item into grouping
             select new {
                 grouping.Key,
                 Count = grouping.Count()
             };

For sample data of:

var customers = new List<Customer>
{
    new Customer { Name = "a", City = "a" },
    new Customer { Name = "a", City = "a" },
    new Customer { Name = "a", City = "b" },
    new Customer { Name = "b", City = "b" }
};

Result is:

enter image description here

Notice that grouping by the Customer object uses its Equals and GetHashCode for comparing the objects then make sure to override them. You can look at this question

Also see that all properties of the object are properties in Key which does not align with your example output but does align with the provided GroupResult you showed

Community
  • 1
  • 1
Gilad Green
  • 36,708
  • 7
  • 61
  • 95