使用LINQ比较两个列表

时间:2015-03-10 20:39:47

标签: linq

public class MyClass
{        
    public int key { get; set; }
    public string fld { get; set; }

    public MyClass(int key, string fld)
    {
        this.key = key;
        this.fld = fld;
    }
}
public class MyTest()
{
    MyClass a = new MyClass(1, "apple");
    MyClass b = new MyClass(2, "peach");
    MyClass c = new MyClass(3, "banana");
    MyClass d = new MyClass(2, "orange");
    MyClass e = new MyClass(4, "pear");

    List<MyClass> myList1 = new List<MyClass>();
    myList1.Add(a);
    myList1.Add(b);    
    myList1.Add(e);    

    List<MyClass> myList2 = new List<MyClass>();
    myList2.Add(a);
    myList2.Add(d);
    myList2.Add(c);
}

我想在xml输出中得到myList1和myList2的比较。  在这种情况下,两个列表都具有相同的密钥1.无需输出此密钥。  关键2 fld是不同的。因此,记录第一个列表fld值。  第一个列表没有键3,换句话说,我们可以认为它已从列表中删除1.因此,记录键3和空fld。第一个列表有键4,而第二个列表没有。所以把它保存在日志中。  所以预期的输出是:

<lists> 
  <list>
    <key>2</key>
    <fld>peach</fld>
  </list>
  <list>
    <key>3</key>
    <fld></fld>
  </list>
  <list>
    <key>4</key>
    <fld>pear</fld>
  </list>
<lists> 

任何人都可以了解如何在LINQ中实现它吗?

2 个答案:

答案 0 :(得分:0)

如果我理解你,你想要将A和B列表与3组结果进行比较:

  • 两个列表中具有相同ID但不同的&#34;值&#34;
  • 的项目
  • 列表A中的项目但不在列表B中
  • 列表B中的项目但不在列表A中

您可以在三个查询中执行此操作:

var differentValues = from a in myList1
                      join b in myList2 on a.key = b.key
                      where a.fld != b.fld
                      select a;

var missingKeysFrom1 = myList2.Where(b => !myList1.Any(a => a.key == b.key));

var missingKeysFrom2 = myList1.Where(b => !myList2.Any(a => a.key == b.key));

可以通过创建IEqualityProvider<MyClass>来简化一些事情,但除非你有重大的性能问题(或者经常执行这些类型的查询),否则它可能不值得。< / p>

请注意,如果您使用Dictionary<int, string>而不是自定义类型列表,则查询会更快。

Linq用于查询,而不是创建XML。

答案 1 :(得分:0)

我在上面的评论中指出,由于需要处理不匹配的密钥和不匹配的值的多种考虑因素,我可能会选择使用与Linq不同的方法,同时完全省略所有对齐的记录。我认为在字典上使用标准循环可能会表达你的意图更清晰。

var itemDictionary = myList1.ToDictionary(item => item.key, item => item.fld);
foreach (var item in myList2) 
{
    if (itemDictionary.ContainsKey(item.key)) 
    {
        if (itemDictionary[item.key].Equals(item.fld))
            itemDictionary.Remove(item.key);
    }
    else 
    {
        itemDictionary.Add(item.key, string.Empty);
    }
}

这似乎可以解决您所提出的问题。它将您的第一个列表加载到字典中,然后针对第二个列表循环以查找差异,并有条件地添加具有空字段的新键,符合您的规范。如果我们将这个字典投射到XML之后......

var xml = new XElement("lists", 
            (from pair in itemDictionary 
             select new XElement("list", 
                new XElement("key", pair.Key), 
                new XElement("fld", pair.Value))
            ).ToArray()
          );

..我们得到以下输出,它看起来也符合您的规范(当您通过评论时,订单无关紧要)。

<lists>
  <list>
    <key>3</key>
    <fld></fld>
  </list>
  <list>
    <key>2</key>
    <fld>peach</fld>
  </list>
  <list>
    <key>4</key>
    <fld>pear</fld>
  </list>
</lists>