【问题标题】:Removing duplicates based on column field and modify it根据列字段删除重复项并对其进行修改
【发布时间】:2015-01-28 17:00:23
【问题描述】:

假设我们有以下 List/IEnumerable

Program : CPE, ECE

旧名单:

Name            Assigned_Area    Program
Ivan Matala     Mathematics      CPE
Ivan Matala     Mathematics      ECE
Jeremy Cruz     Science          ECE
Ivan Matala     Science          CPE
NJ Aquino       Engineering      CPE
MJ Catanaoan    Engineering      ECE      

新列表:

Name            Assigned_Area    Program
Ivan Matala     Mathematics      All Programs
Jeremy Cruz     Science          ECE
Ivan Matala     Science          CPE
NJ Aquino       Engineering      CPE
MJ Catanaoan    Engineering      ECE    

基本上,我想做的是合并每条'Name'和'Assigned_Area'字段相同的记录,如果每条记录都有两个程序(在我们的例子中:'CPE'和'ECE'),那么它应该只是折叠成一行,其 Program 现在是“All Programs”。

我们如何使用 LINQ 做到这一点?

到目前为止我尝试的是以下不完整的代码

var newlist = oldlist.GroupBy(x => x.Assigned_Area);

基本上,我正在考虑将那些具有相同分配区域的记录分组,但上面的代码不完整,因为它只考虑一个字段(我需要考虑 2 个字段,即“名称”和“分配区域”),然后,如果每个分组的计数为 2,则计数错误,如果计数为 2,则我会将其折叠为一条记录,并将程序替换为“所有程序”。


后续问题,但与上述有关..

上述问题适用于非匿名类。基本上,我真正的问题是,我有以下代码

  public IEnumerable GetOfficialList(int visitID)
        {
            db = new PACUCOADB5Entities();

            var x = (from a in db.Accreditor_Program
                     orderby a.Accreditor.Given_Name, a.Accreditor.Middle_Initial, a.Accreditor.Surname, a.Assigned_Area, a.Program.Requested_Program ascending
                     where a.Program.Visit.VisitID == visitID
                     select new
                     {
                         a.Accreditor.Title,
                         a.Accreditor.Given_Name,
                         a.Accreditor.Middle_Initial,
                         a.Accreditor.Surname,
                         a.Assigned_Area,
                         a.Program.Requested_Program
                     }).ToList();

         return x
     }

如您所见,“x”是我的列表/IEnumerable,我试图将相同的概念应用于我正在处理的代码......基本上,我也想做同样的事情,但我的尝试没有成功以下代码

var newx = x.GroupBy(xx => new {xx.Title,xx.Given_Name,xx.Middle_Initial,xx.Surname,xx.Assigned_Area})
                .Select(xx => new {xx.Key.Title, xx.Key.Given_Name, xx.Key.Middle_Initial, xx.Key.Surname, xx.Key.Assigned_Area, xx.Count() == 2 ? "All Programs" :x.First(y => y.Title == xx.Key.Title && y.Given_Name == xx.Key.Given_Name && y.Middle_Initial == xx.Key.Middle_Initial && y.Surname == xx.Key.Surname && y.Assigned_Area == xx.Key.Assigned_Area).Requested_Program));

但通过我的智能感知错误

我们如何解决它?给定该代码,我们如何删除重复项。谢谢

【问题讨论】:

    标签: c# linq duplicate-removal


    【解决方案1】:
    oldList.GroupBy(x => new { x.Name, x.AssignedArea })
           .Select(g => g.Count() == 1
               ? new Entity(g.Key.Name, g.Key.AssignedArea, g.Single().Program)
               : new Entity(g.Key.Name, g.Key.AssignedArea, "All programs")
           );
    

    这里Entity 是您的类,其中包含NameAssignedAreaProgram 字段(代码中没有它的名称)。所有这些都将在程序数可能是 1 或 2 的假设下工作

    【讨论】:

    • Entity类型不是普通类,而是匿名类型怎么办
    • 这不是问题。只需在 select 中创建匿名类。 F.e. new { g.Key.Name, g.Key.AssignedArea, g.Count() == 1 ? g.Single() : "All programs" }.
    • 你能看看这个吗? puu.sh/f8yRl/95af8d1c34.png 谢谢.. 我试过你的代码,但智能感知说,i.stack.imgur.com/9Al12.png
    • 哦,当然。应该是new { g.Key.Name, g.Key.Assigned_Area, Program = g.Count() == 1 ? g.Single().Program : "All programs" }。必须为匿名类的字段命名。
    【解决方案2】:

    这将起作用:

    var result = v.GroupBy(x => new { x.Name, x.Assigned_Area})
                  .Select(x => new EntityName(x.Key.Name, 
                                              x.Key.Assigned_Area, 
                                              x.Count() == 2 ? "All Programs" :v.First(y => y.Name == x.Key.Name && y.Assigned_Area== x.Key.Assigned_Area).Program) );
    

    Demo

    【讨论】:

    • @Shree,我在更新问题时使用了您的代码,概念相同但情况不同。可能出了什么问题?谢谢
    • 请注意,我的Select 实际上调用了类构造函数,而您再次创建了一个匿名对象。我怀疑这就是原因。
    【解决方案3】:

    可能有更好的方法,但这是我的尝试:

    Person[] r = list.GroupBy(p => new { p.Name, p.AssignedArea })
                     .Select(g => g.ToArray())
                     .Select(g => g.Length > 1
                                  UpdateProgram(g.First()) :
                                  g.First())
                     .ToArray();
    
    private static Person UpdateProgram(Person p)
    {
        p.Program = "All Programs";
        return p;       
    }
    

    但我个人会使用分组表达式和常规 foreach 循环:

    foreach (var g in list.GroupBy(p => new { p.Name, p.AssignedArea }))
    {
        var p = g.First();
        if (g.Count() > 1)
        {
            p.Program = "All Programs";
        }
        yield return p;
    }
    

    【讨论】:

    • Name 要求怎么样?
    • 优先选择分组 + foreach 循环是由于性能原因还是可读性?
    • @shree.pat18:纯 LINQ 在没有赋值时运行良好。正如您在其他答案中看到的那样,它引入了混乱并降低了可读性从而降低了可维护性。
    【解决方案4】:

    我确实接受了Mark Shevchenko 的答案,并考虑到具有相同名称、AssisgnedArea 和 Program 的多行:

    list
    .GroupBy(x => new { x.Name, x.Area })
    .Select(g =>
        g.Select(x=>x.Programs).Distinct().Count() == 1 ?
        new Data {Name=g.Key.Name, Area=g.Key.Area, Programs=g.First().Programs} :
        new Data {Name=g.Key.Name, Area=g.Key.Area, Programs="All programs"});
    

    您可以使用以下方法进行测试:

    public struct Data
    {
        public string Name;
        public string Area;
        public String Programs;
    }
    
    void Main()
    {
        var list= new List<Data>()
        { 
            new Data(){ Name="Ivan Matala", Area = "Mathematics", Programs = "CPE" },
            new Data(){ Name="Ivan Matala", Area = "Mathematics", Programs = "ECE" },
            new Data(){ Name="Jeremy Cruz", Area = "Science", Programs = "ECE" },
            new Data(){ Name="Ivan Matala", Area = "Science", Programs = "CPE" },
            new Data(){ Name="NJ Aquino", Area = "Engineering", Programs = "CPE" },
            new Data(){ Name="MJ Catanaoan", Area = "Engineering", Programs = "ECE" },
            new Data(){ Name="MJ Catanaoan", Area = "Science", Programs = "CPE" },
            new Data(){ Name="MJ Catanaoan", Area = "Science", Programs = "CPE" }
        };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2013-12-03
      • 2019-08-04
      • 1970-01-01
      • 2021-01-10
      相关资源
      最近更新 更多