简体   繁体   English

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

[英]Compare elements of an object resides in two list - one on one using LINQ

I'm trying to find out is there any better way other than Enumerable.Range in WHERE clause to compare object's elements one on one. 我试图找出除了Enumerable.Range以外的任何更好的方法在WHERE子句中一对一地比较对象的元素。

It could be a parallel since We're comparing one on one here. 它可能是一个平行线,因为我们在这里一对一比较。

For example: House.Windows[0].color != House1.Windows[0].color and then movenext to House.Windows[1].color != House1.Windows[1].color and so on... 例如: House.Windows[0].color != House1.Windows[0].color然后movenext到House.Windows[1].color != House1.Windows[1].color等...

Type will be same in both list. 两个列表中的类型都相同。

    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()
                                             };            

    }
}

Use Enumerable.Zip if you are comparing one by one: 如果要逐个比较,请使用Enumerable.Zip

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

This returns collection of boolean values for one by one comparison of colors. 这将返回布尔值的集合,以逐一比较颜色。 You can use Any(b => !b) to check if there is any non equal color. 您可以使用Any(b => !b)来检查是否存在任何不相等的颜色。

Keep in mind, that both windows lists should have same length (only corresponding elements will produce result). 请记住,两个窗口列表应该具有相同的长度(只有相应的元素才会产生结果)。 So, you can start from checking length of lists before doing zip. 因此,您可以在执行zip之前检查列表的长度。 If items count is different, then lists are not same. 如果项目计数不同,则列表不相同。


In order to compare windows you should override Equals and GetHashCode methods: 为了比较窗口,您应该重写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;
    }
}

Here is house class slightly improved: 这里的房子类略有改进:

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;
    }
}

With this fluent API you can create houses like 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");

And finding changed and new windows will look like: 找到更改后,新窗口将如下所示:

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

You can use Parallel.For in this context since you are comparing two lists element by element and without editing (if you need to edit you have to use lock): 您可以在此上下文中使用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)
{
}
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM