Использование List <Person> Distinct () для возврата 2 значений

2

У меня есть класс Person с свойствами Name и AreaID.

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

   // snip
}

У меня есть List<Person> с потенциалом для сотен объектов Person в списке. например, 100 человек с AreaID = 1 и 100 человек с AreaID = 2

Я хочу вернуть отдельный список AreaID и сколько людей имеет этот AreaID.

Например, AreaID = 1 чел. = 100 AreaID = 2 человека = 100

  • 0
    Может быть, вам стоит попробовать группирующую конструкцию. Я удивлен, что никто еще не упомянул это;)
Теги:
linq
ienumerable
c#-3.0

10 ответов

5
Лучший ответ

Похоже, вы хотите сгруппировать по ID области:

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

Я использую "группу 1", чтобы указать, что я действительно не забочусь о данных в каждой группе - только счет и ключ.

Это неэффективно в том, что он должен буферизовать все результаты для группировки - вы хорошо сможете использовать Reactive LINQ в .NET 4.0, чтобы сделать это более эффективно, или вы, безусловно, можете использовать нажмите LINQ, если хотите. Опять же, для относительно небольших наборов данных это, вероятно, не имеет значения:)

  • 0
    Хороший момент в группе 1 по. Влияет ли это на реальную производительность, учитывая, что он использует person.AreaID для группировки в любом случае?
  • 0
    @Reed: Это означает, что, если вы транслируете Person с диска, он получает право на сборку мусора раньше. Не проблема в большинстве случаев, хотя.
6

Используйте метод GroupBy.

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

var areas = list.GroupBy( p => p.AreaID )
                .Select( g => new {
                    AreaID = g.Key,
                    Count = g.Count()
                 });
  • 1
    Если вы группируете по AreaID, не будет ли ключ уже AreaID, поэтому вы хотите g.Key вместо g.Key.AreaID ?
  • 0
    Ах да, я повторял шаблон, который недавно использовал, когда у меня был составной ключ, и мне нужно было использовать свойство ключа. Я исправлю это.
1

Неожиданно никто не рекомендовал отменять Equals и GetHashCode. Если вы это сделаете, вы можете сделать следующее:

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

Или даже

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

Это дает вам больше гибкости, - нет необходимости в бесполезном анонимном классе.

0

вы можете использовать list.GroupBy(x => x.AreaID);

0

Вы можете попробовать следующее:

var groups = from person in list
             group person by person.AreaID into areaGroup
             select new {
                 AreaID = areaGroup.Key,
                 Count = areaGroup.Count()
             };
0

Вместо отдельного использования используйте GroupBy или более сжатый оператор LINQ:

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);
  • 1
    Что такое "n" в части "группа n"?
  • 0
    Спасибо - это была плохая опечатка :)
0

Что-то вроде этого, возможно?

            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 ();
  • 0
    хорошо я немного опоздал
0
return list.GroupBy(p => p.AreaID)
    .Select(g => new { AreaID = g.Key, People = g.Count() });
0
        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);
        }
0

ToLookup() сделает то, что вы хотите.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню