Question

I have a Person class, with Name and AreaID properties.

public class Person
{
   public string Name;
   public int AreaID;

   // snip
}

I have a List<Person> with the potential for hundreds of Person objects in the list. e.g., 100 Persons with AreaID = 1 and 100 Persons with AreaID = 2

I want to return distinct list of AreaID's and how many Persons have that AreaID.

For example, AreaID = 1 Persons = 100 AreaID = 2 Persons = 100

Was it helpful?

Solution

Looks like you want to group by area ID then:

var groups = from person in persons
             group 1 by person.AreaID into area
             select new { AreaID = area.Key, Persons = area.Count() };

I'm using "group 1" to indicate that I really don't care about the data within each group - only the count and the key.

This is inefficient in that it has to buffer all the results for the sake of grouping - you make well be able to use Reactive LINQ in .NET 4.0 to do this more efficiently, or you could certainly use Push LINQ if you wanted to. Then again, for relatively small datasets it probably doesn't matter :)

OTHER TIPS

Use the GroupBy method.

var list = ...list of Persons...

var areas = list.GroupBy( p => p.AreaID )
                .Select( g => new {
                    AreaID = g.Key,
                    Count = g.Count()
                 });

Surprisingly nobody advised to override Equals and GetHashCode. If you do so you can do folowing:

 List<Person> unique = personList.Distinct();

Or even

 List<Person> areaGroup = personList.GroupBy(p => p.AreaID);
 List<Person> area1Count = personList.Where(p => p.AreaID == 1).Count();

This gives you more flexibility, - no need in useless anonymous class.

return list.GroupBy(p => p.AreaID)
    .Select(g => new { AreaID = g.Key, People = g.Count() });

you could use list.GroupBy(x => x.AreaID);

You can try this:

var groups = from person in list
             group person by person.AreaID into areaGroup
             select new {
                 AreaID = areaGroup.Key,
                 Count = areaGroup.Count()
             };
        var people = new List<Person>();

        var q = from p in people
                group p by p.AreaId into g
                select new { Id = g.Key, Total = g.Count() };


        people.Add(new Person { AreaId = 1, Name = "Alex" });
        people.Add(new Person { AreaId = 1, Name = "Alex" });
        people.Add(new Person { AreaId = 2, Name = "Alex" });
        people.Add(new Person { AreaId = 3, Name = "Alex" });
        people.Add(new Person { AreaId = 3, Name = "Alex" });
        people.Add(new Person { AreaId = 4, Name = "Alex" });
        people.Add(new Person { AreaId = 2, Name = "Alex" });
        people.Add(new Person { AreaId = 4, Name = "Alex" });
        people.Add(new Person { AreaId = 1, Name = "Alex" });

        foreach (var item in q)
        {
            Console.WriteLine("AreaId: {0}, Total: {1}",item.Id,item.Total);
        }

Something like this, perhaps ?

            List<Person> persons = new List<Person> ();
            persons.Add (new Person (1, "test1"));
            persons.Add (new Person (1, "test2"));
            persons.Add (new Person (2, "test3"));

            var results = 
                persons.GroupBy (p => p.AreaId);

            foreach( var r in results )
            {
                Console.WriteLine (String.Format ("Area Id: {0} - Number of members: {1}", r.Key, r.Count ()));
            }

            Console.ReadLine ();

Instead of distinct, use GroupBy, or the more succinct LINQ statement:

var results = from p in PersonList
              group p by p.AreaID into g
              select new { AreaID=g.Key, Count=g.Count() };

foreach(var item in results)
    Console.WriteLine("There were {0} items in Area {1}", item.Count, item.AreaID);

ToLookup() will do what you want.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top