【问题标题】:Compare lists and get values with Linq使用 Linq 比较列表并获取值
【发布时间】:2009-07-28 21:45:26
【问题描述】:

我的对象是“MyClass”,具有 2 个属性:Id (int) 和 HourBy (int)

我有两个清单:

var List1 = new List<MyClass>();
var List2 = new List<MyClass>();

我想获得一份清单: - 来自 List1 的对象基于 Id 存在于 List2 中,其中 Hourby (list2)

//#Sample1
//List1 :
List1.add(new MyClass(1,10));
List1.add(new MyClass(2,20));
List1.add(new MyClass(3,30));
//List2 :
List2.add(new MyClass(1,10)); 
List2.add(new MyClass(2,15));
//I'd like to get :
new MyClass(2,5);
new MyClass(3,30);

//Sample2
List1 :
List1.add(new MyClass(1,10));
List1.add(new MyClass(2,20));
List1.add(new MyClass(3,30));
//List2 :
List2.add(new MyClass(1,10)); 
List2.add(new MyClass(2,15));
List2.add(new MyClass(2,2));
//I'd like to get :
new MyClass(2,3);
new MyClass(3,30);

谢谢,

【问题讨论】:

  • 你能确认这是你想要的吗.....你想要返回 list1 中存在于 list2 但在 List2 中具有较低 HourBy 属性值的所有项目,以及所有存在的项目在 List2 中但不在 List1 中?
  • 我同意,散文解释不是很清楚,但例子更清楚地表明了需求。我发现看到人们在他们的答案中使用的不同方法很有趣(尽管它们在功能上并不完全相同)
  • @James :让我试着改写一下。 List1 作为对象,List2 包含 List1 的某个对象的副本。 List2 可以包含多次相同的对象。我想要一个 List2 中不存在的对象的列表,如果存在(一个或多个),则某些必须等于 list1 中的值(HourBy),如果不是该对象出现在结果列表中,则 HourBy 之间的差异 List1和 List2(Id 的总和)
  • @MattH :同意,样本更清晰 :)
  • @Kris,好吧,我想我知道你想做什么。让我更新我的答案!

标签: c# .net linq


【解决方案1】:

您可以通过以下 Linq 语句来做到这一点:

var result = List1.Where(x => !List2.Select(y => y.Id).Contains(x.Id)
    || List2.Single(y => x.Id == y.Id).HourBy < x.HourBy);

最好的问候

【讨论】:

  • 嘿奥利弗,我根据你的例子在我的项目中创建了我的 linq 查询它对我有帮助。谢谢
【解决方案2】:

根据您提供的示例列表,我认为这就是您所追求的...

var list3 = new List<MyClass>();

foreach(var item in list1)
{
   var totalFromOther = list2.Where(x => x.id == item.id).Sum(y => y.HourBy);
   var newItem = new MyClass() { id = item.Id, HourBy = item.HourBy - totalFromOther };
   if(newItem.HourBy > 0)
     list3.Add(newItem);
}

【讨论】:

    【解决方案3】:

    这里有一个解决方案:

            var qry = from ee in
                           (from e1 in list1
                            join e2 in list2 on e1.Id equals e2.Id into gj
                            from e in gj.DefaultIfEmpty()
                            select new { 
                                e1.Id,
                                MainHourBy = e1.HourBy,
                                SecondHourBy = (e == null ? 0 : e.HourBy)
                            })
                       where ee.SecondHourBy < ee.MainHourBy
                       group ee by ee.Id into g
                       select new MyClass
                       {
                           Id = g.Key,
                           HourBy = g.First().MainHourBy - g.Sum(el => el.SecondHourBy)
                       };
    

    【讨论】:

      【解决方案4】:

      我使用此代码,它并不完美,但可以正常工作,并且对于 Linq 中的新手(比如我)可能更清楚

      List< MyClass> listRes = new List< MyClass>();
      foreach ( MyClass item in list1)
      {
          var exist = list2
              .Select(x => x.MyClass)
              .Contains(item);
      
          if (!exist)
              listRes.Add(item);
          else
          {
              var totalFromOther = list2
                  .Where(x => x.MyClass.Id == item.Id)
                  .Sum(y => y.HourBy);
      
              if (item.HourBy != totalFromOther)
              {        
                  item.HourBy = item.HourBy - totalFromOther;
                  listRes.Add(item);
              }            
          }   
      }
      

      感谢您的帮助,

      【讨论】:

        【解决方案5】:
        var agg1 = from l in list1
                   group l by l.ID into g
                   select new { g.Key, Sum = g.Sum(_ => _.HourBy) };
        var agg2 = from l in list2
                   group l by l.ID into g
                   select new { g.Key, Sum = g.Sum(_ => _.HourBy) };
        
        var q = from l1 in agg1
                let l2 = agg2.FirstOrDefault(_ => _.Key == l1.Key)
                let sum = l1.Sum - (l2 != null ? l2.Sum : 0)
                where sum != 0
                select new MyClass(l1.Key, sum);
        
        var list3 = q.ToList();
        

        【讨论】:

        • 我对“让”子句不太熟悉。它是为查询评估一次,还是在这种情况下每行评估一次?
        【解决方案6】:
        //Group list 2, so there is one entry per ID, with HourBy = total hour by
        var summedL2 = from item2 in List2
                      group item2 by item2.ID into g
                      select new Test(g.Key, g.Sum(item => item.HourBy));
        
        var result = 
                    //Select items from list1
                     from item1 in List1
                     //Left join to our summed List2
                     join item2s in summedL2 on item1.ID equals item2s.ID into tempItem2s
                     from item2 in tempItem2s.DefaultIfEmpty()
                     //Where there is no match, or item2 is < item1
                     where (item2 == null || item2.HourBy < item1.HourBy)
                     //Select a new Test object, with the HourBy changed
                     select new Test(item1.ID, item1.HourBy - (item2 == null ? 0 : item2.HourBy));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-28
          • 1970-01-01
          相关资源
          最近更新 更多