1
votes

I have some data that I would like to count and group by. It looks like this:

Cat Cat Dog Dog Dog

My goal is to get a list of objects that have the name of the animal and the number of times it appears in the data set

Object 1

Name: Cat

NumberAppearances: 2

Object 2

Name: Dog

NumberAppearances: 3

I am trying to do this with a LINQ query and this is what I have but the count is wrong. I think it's counting the length instead of the number of times it appears. How would I modify this?

animalData.Select(x => x.AnimalType).Distinct().ToList().ForEach(a => 

    AnimalObject animal = new AnimalObject();

    animal.Name = a.Name;

    animal.Number = a.Distinct().Count();

    animalList.Add(animal);

});
3
Try animalData.Select(x => x.AnimalType).GroupBy(...). When you're going to use LINQ first do some exercises with all Enumerable extension methods to get them into your system. - Gert Arnold
Can you explain why you've inserted a bunch of "distinct" clauses? The point of a distinct clause is to remove duplicates which then makes it impossible to count the number of duplicates. I am interested to learn why people make mistakes when programming; what led you to believe that removing the duplicates would be a good way to count the duplicates? - Eric Lippert
What is the type of AnimalType? - Eric Lippert

3 Answers

5
votes

This is all you need to accomplish your task:

var result = animalData.GroupBy(x => x.AnimalType).Select(g => new AnimalObject 
             {
                 Name = g.Key,
                 Number = g.Count()
             }).ToList();

foreach (var e in result)
    Console.WriteLine($"Name: {e.Name} \n NumberAppearances: {e.Number}");

note -

  1. as your LINQ query is currently written, you need not call distinct nor ToList as the former will result in the incorrect outcome and the latter is unnecessary.
  2. stick to good naming conventions, you don't need the Object suffix after the type name so just Animal will suffice.
0
votes

You can use this one without creating a new object, with the help of Dictionary:

var animalCounts = animalList.GroupBy(a => a.AnimalType).ToDictionary(
                                 grp => grp.Key, grp => grp.ToList().Count());
foreach(var animalCount in animalCounts) {
   Console.WriteLine($"Name: {animalCount.Key}{Environment.NewLine}NumberOfApperances: {animalCount.Value}");
}
0
votes

Group the data by AnimalType, then transform it to AnimalObject.

var result = animalData.GroupBy(x => x.AnimalType)
                            .Select(g => new AnimalObject { Name = g.Key, Number = g.Count() })
                            .ToList();