【问题标题】:How do I get the objects from a list of objects which contain a duplicate property inside of another list in the object?如何从对象列表中获取对象,这些对象列表中包含对象中另一个列表中的重复属性?
【发布时间】:2021-10-25 00:23:21
【问题描述】:

我有以下对象示例:

public class Event
{
...
    public NextEventStatus NextStatus { get; set; }
...
}

public class NextEventStatus 
{
    public List<Person> People{ get; set; }
}

public class Person
{
    public string Name { get; set; }

    public string Email { get; set; }
}

如果我有例如List&lt;Event&gt; 包含 3 个 Event 对象,每个对象中都有 NextStatus 属性,其中包含 People 类型的 List&lt;Person&gt; 属性,只有 1 个条目,例如:

//In Event object 1
Name = "person1"
Email = "person1email@anemail.com"

//In Event object 2
Name = "person2"
Email = "person2email@anemail.com"

//In Event object 3
Name = "person1"
Email = "person1email@anemail.com"

是否有可能获得在 Email 内包含相同 Email 属性的唯一 Event 对象,因此对于包含上述内容的对象,它将返回完整的事件对象 1 和 3,但是不是事件对象 2?所以它在列表内的列表中寻找重复项。

我已经研究过如何做到这一点,但是当您需要访问另一个列表时,您对如何执行 GroupBy 有点迷失,因为初始对象将是 List&lt;Event&gt;,然后有一个属性 @987654332 @ 这是一个 List&lt;Person&gt; 这是在其中寻找重复项的地方

var originalEventList = new List<Event>();
//Add objects to list here...

var eventListWithDuplicates = originalEventList.GroupBy(x => x.NextStatus.People) ...

【问题讨论】:

  • 如果 event1 和 event 3 各有 2 个人呢?人们总是按照相同的顺序排列吗?顺序重要吗?您本质上是否想要“同一人群参加的所有活动的列表”?
  • 你的意思是如果例如event1 和 event3 都有一个额外的人,但那个额外的人不是同一个人,所以两者之间只有 1 个共同的重复人?从事件列表中,我基本上需要其中存在重复的所有事件对象/List&lt;Person&gt; 内部的属性相同,所以如果例如只看Person的Name属性,所有相同Name属性出现多次的Event对象
  • 如果e1有p1&p2,e2有p2&p3,e3有p1,那么e1&e2分享p2,e1&e3分享p3,你期望什么答案?

标签: c# list linq duplicates


【解决方案1】:

我认为您需要以下内容:

var grouped =
    from e in originalEventList
    from p in e.NextStatus.Persons
    group e by p.Email into g
    where g.Count() > 1
    select g;

var result = grouped.SelectMany(x => x).Distinct();

【讨论】:

    【解决方案2】:

    这可以用 LINQ 完成,但我不确定它是否比非 LINQ 版本更容易理解

    var em = new Dictionary<string, Event>();
    var ev = new HashSet<Event>();
    
    foreach(var e in eventList)
      foreach(var p in e.NextStatus.People)
        if(!em.TryAdd(p.Email, e)){
           ev.Add(e);
           ev.Add(em[p.Email]);
        }
    

    ev 现在包含一组只有非常善于交际的人才能参加的活动:)。那么它是怎样工作的?我们列举了所有的事件和所有的人,试图将每个电子邮件地址与正在参加的特定事件一起添加到字典中。如果尝试将电子邮件添加到字典中返回 false,则表示“字典已包含该电子邮件”。因为我们之前已经看到这封电子邮件,这意味着当前人员至少参加了一个其他活动,因此应该将字典 d[p.Email] 中的这个事件 ethat 事件添加到集合中。 HashSet 不允许重复,所以如果一个事件在它之前已经被看到,它就不会被添加。请注意,电子邮件将区分大小写,并且“bill@microsoft.com”不是“Bill@microsoft.com”

    我想 LINQ 方法可能看起来像

    eventList
      .SelectMany(e => e.NextStatus.People, (E, P) => new { E, P })
      .GroupBy(ep => ep.P.Email)
      .Where(g => g.Count > 1)
      .SelectMany(g => g.E)
      .Distinct()
    

    在这里,它将 eventList 解压缩为具有单个事件/人员对的匿名类型,按人员电子邮件对其进行分组,将它们过滤到仅包含多个事件的组,解压缩 list-of-list-of-事件到单个事件列表,然后使用 distinct 丢弃重复的事件。它的效率大大低于第一种方法

    【讨论】:

      猜你喜欢
      • 2014-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-02
      • 1970-01-01
      • 2017-06-29
      • 2021-08-10
      • 1970-01-01
      相关资源
      最近更新 更多