linq 比较两个不同类别列表中的单个属性

i7uaboj4  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(157)

我一直在阅读有关如何做到这一点的最后2天,我仍然是在一个茫然的理解如何做到这一点。

**目标:**通过仅比较“existing Database Motors”列表和“New Excel Motors”列表的名称属性,将两个列表进行比较。我不想比较任何其他属性。返回仅对“existing Database Motors”唯一的对象列表。

这是我正在尝试做的事情的简化版本:
自订类别:

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

列出这些自定义类:

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

我想返回这样的东西(我知道这行不通,“.Except”只接受泛型):

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

我认为我有4个选择:
选项1:使用LINQ“其中:
选项2:使用扩展方法
选项3:Linq,除非使用自定义的IEqualityComparer
选项4:可枚举。序列相等(列表1,列表2)
我在这方面遇到了很多麻烦。我在努力学习LINQ、Except、IEqualityCompare等是如何工作的。我开始觉得自己真的很笨,我以前从来没有觉得自己这么无能过。我是C#新手,而且我甚至很难理解关于这个东西的MS文档。我不知道如何阅读Enumerable。除了方法文档。API文档是我以前从未经历过的...如果你有关于我如何学习如何阅读这些类/方法的文档的建议,我将不胜感激。
请从根本上解释为什么除了不起作用。我很困惑。

lb3vh1jj

lb3vh1jj1#

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

x759pob22#

如果我没理解错的话,你能不能通过将每个电机的名称与excel电机名称列表进行比较来过滤数据库电机,并返回没有匹配项的条目?

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

此外,在“选项”列表中,您省略了使用一个简单的for循环。上面的代码可以写为:

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

kninwzqo3#

您也可以使用“LEFT JOIN”来执行下列工作:

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

相关问题