【问题标题】:Using List<Person> Distinct() to return 2 values使用 List<Person> Distinct() 返回 2 个值
【发布时间】:2009-10-22 14:30:40
【问题描述】:

我有一个Person 类,具有NameAreaID 属性。

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

   // snip
}

我有一个List&lt;Person&gt;,列表中可能包含数百个 Person 对象。 例如,AreaID = 1 的 100 个人和 AreaID = 2 的 100 个人

我想返回不同的 AreaID 列表以及有多少人拥有该 AreaID。

例如, AreaID = 1 人 = 100 AreaID = 2 人 = 100

【问题讨论】:

  • 也许你应该尝试一个分组结构。我很惊讶还没有人提到这一点;)

标签: c# .net linq c#-3.0 ienumerable


【解决方案1】:

使用 GroupBy 方法。

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

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

【讨论】:

  • 如果你按 AreaID 分组,键不是已经是 AreaID,所以你想要g.Key 而不是g.Key.AreaID
  • 啊,是的——我在重复我最近使用的一种模式,我有一个复合键并且需要使用键的属性。我会解决的。
【解决方案2】:

看起来你想按区域 ID 分组:

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

我使用“组 1”表示我真的不关心每个组中的数据 - 只关心计数和键。

这是低效的,因为它必须缓冲所有结果以进行分组 - 您可以在 .NET 4.0 中使用 Reactive LINQ 来更有效地执行此操作,或者您当然可以使用 Push LINQ想要。再说一次,对于相对较小的数据集,这可能无关紧要:)

【讨论】:

  • 第 1 组的好点。但是,考虑到它仍然使用 person.AreaID 进行分组,这对实际性能有很大影响吗?
  • @Reed:这意味着如果您从磁盘流式传输 Person,它会更早地进行垃圾收集。不过在大多数情况下都不是问题。
【解决方案3】:

令人惊讶的是,没有人建议覆盖 EqualsGetHashCode。如果这样做,您可以执行以下操作:

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

甚至

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

这给了你更多的灵活性——不需要无用的匿名类。

【讨论】:

    【解决方案4】:
    return list.GroupBy(p => p.AreaID)
        .Select(g => new { AreaID = g.Key, People = g.Count() });
    

    【讨论】:

      【解决方案5】:

      你可以使用list.GroupBy(x =&gt; x.AreaID);

      【讨论】:

        【解决方案6】:

        你可以试试这个:

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

        【讨论】:

          【解决方案7】:
                  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);
                  }
          

          【讨论】:

            【解决方案8】:

            大概是这样的吧?

                        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 ();
            

            【讨论】:

              【解决方案9】:

              使用 GroupBy 或更简洁的 LINQ 语句代替 distinct:

              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);
              

              【讨论】:

              • “组n”部分中的“n”是什么?
              【解决方案10】:

              ToLookup() 会做你想做的事。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-04-08
                • 2012-10-07
                • 2016-05-26
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多