我有一个对象和两个列表,如下所示:

    public class MyObject
    {
        public int Key;
        public DateTime Day;
        public decimal Value;
    }

    List<MyObject> listA = new List<MyObject>()
    {
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = 8 },
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 18), Value = 8 },
        new MyObject() { Key = 2, Day = new DateTime(2012, 12, 17), Value = 8 },
        new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 4 },
        new MyObject() { Key = 4, Day = new DateTime(2012, 12, 17), Value = 4 }
    };

    List<MyObject> listB = new List<MyObject>()
    {
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = 2 },
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 18), Value = 8 },
        new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 8 },
        new MyObject() { Key = 4, Day = new DateTime(2012, 12, 17), Value = 4 },
        new MyObject() { Key = 5, Day = new DateTime(2012, 12, 17), Value = 10 }
    };

我要找的结果是:
    List<MyObject> listChanges = new List<MyObject>()
    {
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = -6 },
        new MyObject() { Key = 2, Day = new DateTime(2012, 12, 17), Value = -8 },
        new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 4 },
        new MyObject() { Key = 5, Day = new DateTime(2012, 12, 17), Value = 10 }
    };

本质上,我试图创建一个列表,其中包含将list a变成listB所需的更改因此,虽然可以使用Except和Intersect from LINQ,但我认为它们在执行这样的任务时不会有最好的性能,因为您仍然需要另一个比较来获得值的差异。
我的一个想法是:如果我遍历lista,我可以从lista和listb中删除该项(如果找到了,此时我可以确定正负差)。一旦我完成lista,listb将只包含添加。
我怎样才能得到更改结果?

最佳答案

这样就可以了如果您的任何Key/Day组合在两个输入中都不唯一,则会引发异常。

public static IEnumerable<MyObject> GetChanges(
    IEnumerable<MyObject> from, IEnumerable<MyObject> to)
{
    var dict = to.ToDictionary(mo => new { mo.Key, mo.Day });

    // Check that keys are distinct in from, too:
    var throwaway = from.ToDictionary(mo => new { mo.Key, mo.Day });

    // Adjustments of items found in "from"
    foreach (MyObject mo in from)
    {
        var key = new { mo.Key, mo.Day };
        MyObject newVal;
        if (dict.TryGetValue(key, out newVal))
        {
            // Return item indicating adjustment
            yield return new MyObject {
                Key = mo.Key, Day = mo.Day, Value = newVal.Value - mo.Value };
            dict.Remove(key);
        }
        else
        {
            // Return item indicating removal
            yield return new MyObject {
                Key = mo.Key, Day = mo.Day, Value = -mo.Value };
        }
    }

    // Creation of new items found in "to"
    foreach (MyObject mo in dict.Values)
    {
        // Return item indicating addition
        // (Clone as all our other yields are new objects)
        yield return new MyObject {
            Key = mo.Key, Day = mo.Day, Value = mo.Value };
    }
}

您可以通过删除from上的唯一性检查或动态执行(尝试将每个项的关键部分添加到HashSet)来加快速度,但我不认为您可以避免在to的部分上循环两次-一次构建字典,一次返回其余部分。

关于c# - 如何区分两个列表并获得净变化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13924169/

10-13 03:36