简体   繁体   中英

Compare single property within Two Lists of Different Classes

I have been reading about how to do this for the last 2 days and I still am at a loss of understanding how to do it.

Goal: Compare list of "existing Database Motors" to list of "New Excel Motors" by comparing the name property of each list only. I do not want to compare any of the other properities. Return a list of objects that are unique to only "existing Database Motors".

This is a simplified version of what I am trying to do:

Custom Classes:

public class motor_Excel
{
    public string MotorName; //the field I need to be able to compare with motor_Database.iName
    public string MotorVoltage;
    public double MotorHP;
}

public class motor_Database
{
    public int iID;
    public string iName; //the field I need to be able to compare with motor_Excel.MotorName
    public int iCircuit;
}

Make lists of those custom classes:

List<motor_Database> equipList_EX = ReadDatabase(DBpath.txt); //create new custom obj list of from database
List<motor_Excel> equipList_Update = ReadExcel(Excelpath.txt); //create new custom obj list of from excel

I would like to return something like this (I know that this wont work, ".Except" only takes generics):

List<motor_Database> result = equipList_EX.iName.Except(equipList_Update.MotorName)

I believe that I have 4 options:

Option 1: Use LINQ "Where:
Option 2: Use extension method
Option 3: Linq Except with custom IEqualityComparer
Option 4: Enumerable.SequenceEqual( list1, list2)


I have been having SO much trouble with this. Im struggling to learn how the LINQ, Except, IEqualityCompare, etc work. Im starting to feel really dumb, I've never felt so incapable before. Im new to C#, and Im struggling to even comprehend the MS.documentation on this stuff . I can't make any sense of how to read the Enumerable.Except Method docs. The API documentation is like nothing I have experienced before... If you have recommendations on how I can learn how to read documentation for these classes/methods I would appreciate it.

Please, explain at fundamental levels why except wont work. Im so confused.

The reason you're confused is because you're looking at the API reference, not LINQ's documentation . You'd have the same problem with any language, any API.

The assignment text says nothing about multiple classes:

Compare list of "existing Database Motors" to list of "New Excel Motors" by comparing the name property of each list only.

If you were comparing Motor objects you'd only need a single Motor class. In this case though you're comparing only names. You're checking to find the Motor objects whose names don't appear in a List of new motor names.

Except isn't useful here. As the description says :

Produces the set difference of two sequences.

This isn't idle wording. Just like SQL's EXCEPT the type/shape of the two sets must be the same. That's why the method only works with items of the same type .

What you want can be done using Where and List<string>.Contains

List<Motor> motors=ReadDatabase(DBpath.txt); 
List<string> new_names=ReadExcel(...);

var old_motors=motors.Where(m=>!new_names.Contains(m.Name))
                     .ToList();

You can speed this up if you use a HashSet

...
var names_set=new HashSet<string>(new_names);
var old_motors=motors.Where(m=>!names_set.Contains(m.Name))
                     .ToList();

If I understand the question correctly, couldn't you just filter the database motors by comparing each one's name to the list of excel motor names, and return the entries that don't have a match?

List<motor_Database> dbMotors = ReadDatabase(DBpath.txt); 
List<motor_Excel> xlMotors = ReadExcel(Excelpath.txt);

List<motor_Database> uniqueDbMotors = dbMotors
  .Where(dbMotor => xlMotors.All(xlMotor => xlMotor.MotorName != dbMotor.iName))
  .ToList();

Also, in you list of "options", you left out using a simple for loop. The above code could be written as:

var uniqueDbMotors = new List<motor_Database>();

foreach(var dbMotor in dbMotors)
{
    var foundMatch = false;

    foreach (var xlMotor in xlMotors)
    {
        if (dbMotor.iName == xlMotor.MotorName)
        {
            foundMatch = true;
            break;
        }
    }

    if (!foundMatch) uniqueDbMotors.Add(dbMotor);
}

You can also use "LEFT JOIN" for such task:

List<motor_Database> result = 
    (from ex in equipList_EX
    join up in equipList_Update on ex.iName equals up.MotorName into gj
    from up in gj.DefaultIfEmpty()
    where up == null
    select ex).ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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