比较两个列表,只在Linq中获取不同的项目

时间:2013-12-19 06:38:58

标签: c# linq

我的对象有3个字段 - 学生,学期,科目和标记。我想要一个列表,其中任何主题的标记都不同。

例如:

 First list is 
             Alice, Term1, English,90
             Alice, Term1, Maths, 60
             Alice, Term1, Physics, 30

    Second list is 
             Alice, Term2, English, 95
             Alice, Term2,Maths, 60
             Alice, Term2, Physics, 20

在最终列表中,我只想获得差值

爱丽丝,英语+5 爱丽丝,物理-10 -

如何使用Linq(c#)

执行此操作

3 个答案:

答案 0 :(得分:1)

实际上,有很多方法可以做到这一点。一个提到使用自定义比较器。一个人使用了字典,但这并不是必需的。

// 1) use group by and only select groups with one item in them
var qqq = from r in one.Union(two)
          group r by new { r.Term, r.Mark } into g
          where g.Count() == 1
          select g.First();

// 2) work from a complete list and then remove stuff
var all   = one.Union(two).ToList();

// select only the records that have a count of one
var uniq = from a in all 
           where all.Count(y => y.Term == a.Term && y.Mark == a.Mark) == 1
           select a;

// -or- find all the duplicates and the remove them
var dupes = all.Where(x => all.Count(y => y.Term == x.Term && y.Mark == x.Mark) > 1).ToList();
var uniq  = all.Except(dupes).ToList();

有很多方法可以解决这个问题。

修改

现在我已经有了第二个想法,似乎有一个简单的方法可以一步完成这一切。不确定整个要求,但现在是:

var calcd = from t1 in one
            let t2 = two.FirstOrDefault(x => DataMatch(t1, x))
            where t2 != null
            select new {
                Name = t1.Name,
                Class = t1.Class,
                Change = t2.Mark - t1.Mark
            };

public static bool DataMatch(Data x, Data y)
{
    return x.Name == y.Name && x.Class == y.Class &&
           x.Term != y.Term && x.Mark  != y.Mark;
}

答案 1 :(得分:0)

这可能是你想要的(但不幸的是没有测试......):

        var result = secondList.Union(firstList)
            .GroupBy(m => Tuple.Create(m.Student, m.Subject))
            .ToDictionary(m => m.Key, n => n.OrderBy(m=>m.Term).Select(s => s.Marks).Aggregate((t1, t2) => t2 - t1))
            .Where(m=>m.Value != 0);

答案 2 :(得分:0)

var comparer = new SomeClassComparer(); /*must implement IEaualityComparer<SomeClass>*/
var list1 = new List<SomeClass>() { /*...*/ };
var list2 = new List<SomeClass>() { /*...*/};

var result = list1.Except(list2, comparer).Union(list2.Except(list1, comparer));