比较对象的元素驻留在两个列表中 - 一对一使用LINQ

时间:2013-07-18 12:59:03

标签: c# .net performance linq linq-to-entities

我试图找出除了WHERE子句中的Enumerable.Range以外的任何更好的方法来一对一地比较对象的元素。

这可能是一个平行线,因为我们在这里一对一比较。

例如:House.Windows[0].color != House1.Windows[0].color然后将其移动到  House.Windows[1].color != House1.Windows[1].color等等......

两个列表中的类型都相同。

    public class House
{
    string HouseNmbr;
    List<Window> windows;

}

public class Window
{
    string WSize;
    string WColor;
    bool IsEnergyEff;
}

public static class MyMain
{
    void Main()
    {
        House h1 = new House
        {
            HouseNmbr = "1",
            windows = new List<Window> { 
                new Window {Wsize="1", WColor = "blue",IsEnergyEff = true},
                new Window {Wsize="1", WColor = "black"},
                new Window {Wsize="1", WColor = "red"}
            }
        };

        House h2 = new House
        {
            HouseNmbr = "1",
            windows = new List<Window> { 
                new Window {Wsize="2", WColor = "blue",IsEnergyEff = false},
                new Window {Wsize="2", WColor = "black"}
            }
        };

        //Find the diffs...
        IEnumerable<House> updatesFromHouses = from id in h2 //Since h2 will have updates
                                             join pd in h1
                                             on id.HouseNmbr equals pd.HouseNmbr
                                               select new House
                                             {
                                                 windows = pd.windows.Where(
                                                    wn => Enumerable.Range(0, wn.windows.Count).All(ctr => wn.IsEnergyEff != id.windows[ctr].IsEnergyEff)
                                                 ).ToList()
                                             };            

    }
}

2 个答案:

答案 0 :(得分:3)

如果您逐个比较,请使用Enumerable.Zip

House.Windows.Zip(House1.Windows, (w, w1) => w.color != w1.color);

这将返回布尔值的集合,用于逐个颜色比较。您可以使用Any(b => !b)检查是否有任何不相同的颜色。

请记住,两个窗口列表应该具有相同的长度(只有相应的元素才会产生结果)。因此,您可以在执行zip之前检查列表的长度。如果项目计数不同,则列表不相同。


为了比较窗口,你应该重写Equals和GetHashCode方法:

public class Window
{
    public string Size { get; set; }
    public string Color { get; set; }
    public bool IsEnergySaving { get; set; }

    public Window() { }

    public Window(string size, string color, bool isEnergySaving)
    {
        Size = size;
        Color = color;
        IsEnergySaving = isEnergySaving;
    }

    public override bool Equals(object obj)
    {
        Window other = obj as Window;
        if (other == null)
            return false;

        return Color == other.Color &&
               IsEnergySaving == other.IsEnergySaving;
    }

    public override int GetHashCode()
    {
        int hash = 19;            
        hash = hash * 23 + Color.GetHashCode();
        hash = hash * 23 + IsEnergySaving.GetHashCode();
        return hash;
    }
}

这里的房子类略有改进:

public class House
{
    public House(string number)
    {
        Number = number;
        Windows = new List<Window>();
    }

    public string Number { get; private set; }
    public List<Window> Windows { get; private set; }

    public House WithWindow(string size, string color, bool energySaving = false)
    {
        Windows.Add(new Window(size, color, energySaving));
        return this;
    }
}

使用这种流畅的API,您可以创建这样的房屋:

House h1 = new House("1")
                .WithWindow("1", "blue", true)
                .WithWindow("1", "black")
                .WithWindow("1", "red");

House h2 = new House("1")
                .WithWindow("2", "blue")
                .WithWindow("2", "black");

找到更改后,新窗口将如下所示:

var changedAndNewWindows = h2.Windows.Except(h1.Windows);

答案 1 :(得分:0)

您可以在此上下文中使用Parallel.For,因为您要逐个元素地比较两个列表而不进行编辑(如果您需要编辑,则必须使用锁定):

var count = Math.Min(h1.Windows.Count, h2.Windows.Count);
Parallel.For(0, count, (index)=>{
//Do your operations here
if(h1.Windows[index].Color == h2.Windows[index].Color)
{
}
});