简体   繁体   English

比较2个相同对象类型的列表

[英]Compare 2 lists of same object type

I have 2 lists of a specific type, in this case it is List. 我有2种特定类型的列表,在本例中为List。 In the class DataDictionary there is a property called TableName. 在DataDictionary类中,有一个名为TableName的属性。 I have 2 lists with the same type I am trying to compare. 我有2个要比较的相同类型的列表。 I have other properties aswell which I need to hold association with that specific TableName so I can't just compare them separately. 我还有其他属性,需要与该特定TableName保持关联,因此我不能仅将它们进行单独比较。

I need to find a way to compare the TableName in 2 different lists of DataDictionary and then find which ones they don't have in common. 我需要找到一种方法来比较DataDictionary的2个不同列表中的TableName,然后找到它们没有共同点的那些。 From there I then need to compare all the other properties against the 2 items in each list with the same TableName. 然后,从那里,我需要将所有其他属性与每个具有相同TableName的列表中的2个项目进行比较。

I have tried to use the Except IEnumerate solution which works if you just compare the strings directly but I don't know how to keep the association with the object. 我尝试使用Except IEnumerate解决方案,如果您直接比较字符串,但我不知道如何保持与对象的关联,该解决方案将起作用。

List<DataDictionary> ColumnsDataDict = daDD.getTablesandColumnsDataDictionary();
List<DataDictionary> ColumnsWizard = daWiz.getColumnsWizard();
var newlist = ColumnsWizard.Except(ColumnsDataDict);
foreach(DataDictionary item in newlist)
{
       Console.WriteLine(item.TableName);
}

Here is the DataDictionary class: 这是DataDictionary类:

public string TableName { get; set; }
public string Description { get; set; }
public string TableID { get; set; }
public string ColumnDesc { get; set; }
public string ColumnName { get; set; }

This directly compares the objects, but I just want to compare the TableName property in my DataDictionary class. 这将直接比较对象,但是我只想比较DataDictionary类中的TableName属性。 I want this to then get a list of objects that doesn't have the same table name in each list. 然后,我希望它获得在每个列表中没有相同表名的对象的列表。 Any help is appreciated, thanks! 任何帮助表示赞赏,谢谢!

I don't believe your problem can be solved with LINQ alone and there for I would recommend using a good old loop . 我不相信单独使用LINQ就能解决您的问题,因为我建议您使用一个良好的旧loop

If you want to compare two lists, you will have to use two loops nested in one another. 如果要比较两个列表,则必须使用彼此嵌套的两个loops

Like this: 像这样:

public class Program
{
    public static void Main()
    {
        var listA = new List<Foo>() {
            new Foo() { TableName = "Table A", Value = "Foo 1" },
            new Foo() { TableName = "Table B", Value = "Foo 1" },
        };

        var listB = new List<Foo>() {
            new Foo() { TableName = "Table A", Value = "Foo 10" },
            new Foo() { TableName = "Table C", Value = "Foo 12" },
        };

        foreach (var itemA in listA)
        {
            foreach (var itemB in listB)
            {
                if (itemA.TableName == itemB.TableName)
                {
                    Console.WriteLine($"ItemA's Value: {itemA.Value}");
                    Console.WriteLine($"ItemB's Value: {itemB.Value}");
                }
            }
        }
    }
}

public class Foo
{
    public string TableName { get; set; }
    public string Value { get; set; }
}

At the position where I am printing the values of itemA and itemB you can compare your objects and find the difference between them. 在我打印itemAitemB值的itemA ,您可以比较对象并找出它们之间的差异。

So instead of: 所以代替:

Console.WriteLine($"ItemA's Value: {itemA.Value}");
Console.WriteLine($"ItemB's Value: {itemB.Value}");

Maybe something like this: 也许是这样的:

if (itemA.Value != itemB.Value) //extend the `if` with all the properties you want to compare
{
    Console.WriteLine($"ItemA's Value isn't equal to ItemB's Value");
}

If you need to check if listA doesn't have an entry in listB then you can extend the inner loop like this: 如果您需要检查,如果listA没有一个条目中的listB则可以延长内循环是这样的:

foreach (var itemA in listA)
{
    var found = false;
    foreach (var itemB in listB)
    {
        if (itemA.TableName == itemB.TableName)
        {
            found = true;
        }
    }

    if (found == false)
    {
        Console.WriteLine("ItemA's TableName wasn't found in listB");
    }
}

SOLUTION: 解:

// Merges both objects
List<DataDictionary> duplicatesRemovedLists = ColumnsDataDict.Concat (ColumnsWizard).ToList ();

// Removes common objects based on its property value (eg: TableName)
foreach (var cddProp in ColumnsDataDict) {
  foreach (var cwProp in ColumnsWizard) {
    if ((cddProp.TableName == cwProp.TableName)) {
      duplicatesRemovedLists.Remove (cddProp);
      duplicatesRemovedLists.Remove (cwProp);
    }
  }
}

// Prints expected output
foreach (DataDictionary item in duplicatesRemovedLists) Console.WriteLine (item.TableName);

You can use several LINQ methods implementing a customer IEqualityComparer . 您可以使用几种LINQ方法来实现客户IEqualityComparer For instance having a comparer for the property TableName : 例如,具有属性TableName的比较器:

public class TableNameEqualityComparer : IEqualityComparer<DataDictionary>
{
    public bool Equals(DataDictionary x, DataDictionary y)
    {
        if (x == null && y == null)
        {
            return true;
        }

        return x != null && y != null && x.TableName == y.TableName;
    }

    public int GetHashCode(DataDictionary obj)
    {
        return obj?.TableName?.GetHashCode() ?? 0;
    }
}

Two instances returning true for the Equals method must return the same value for GetHashCode . Equals方法返回true两个实例必须GetHashCode返回相同的值

Just make an instance of your custom comparer. 只需创建您的自定义比较器的实例即可。

var listA = new List<DataDictionary>()
{
    new DataDictionary() {TableName = "Table A"},
    new DataDictionary() {TableName = "Table B"},
};

var listB = new List<DataDictionary>()
{
    new DataDictionary() {TableName = "Table A"},
    new DataDictionary() {TableName = "Table C"},
};

var tableNameComparer = new TableNameEqualityComparer();

And then use it with different LINQ methods: 然后将其与其他LINQ方法一起使用:

// A - B
var listAExceptB = listA.Except(listB, tableNameComparer);
Assert.Collection(listAExceptB,
    x => Assert.Equal("Table B", x.TableName));

// B - A
var listBExceptA = listB.Except(listA, tableNameComparer);
Assert.Collection(listBExceptA,
    x => Assert.Equal("Table C", x.TableName));

// A ∩ B
var listIntersect = listA.Intersect(listB, tableNameComparer);
Assert.Collection(listIntersect,
    x => Assert.Equal("Table A", x.TableName));

// A ∪ B
var listUnion = listA.Union(listB, tableNameComparer);
Assert.Collection(listUnion,
    x => Assert.Equal("Table A", x.TableName),
    x => Assert.Equal("Table B", x.TableName),
    x => Assert.Equal("Table C", x.TableName));

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

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