繁体   English   中英

在 C# 中使用 LINQ 在列表列表中查找和更新值

[英]Using LINQ in C# to find and update values in a list of lists

我有下面列出的三个类:

class OuterObjects
{
    string name;
    List<InnerObjects> myList;
}

class InnerObjects
{
    float small;
    float big;
}

class CorrectValues
{
    string name;
    float correctValue;
}

因此,我的代码遍历所有内容并到达一个点,即我已映射所有 OuterObjects 和 InnerObjects,然后分别使用数据库调用加载 CorrectValues。

所以我有:

List<OuterObjects> theList = [loaded up with many names and InnerObjects]

所以我需要写一些东西,将 go 通过 OuterObjects 并进入 InnerObjects 并找到所有小>大并修复它们。 (float) big 将替换为 CorrectValues 和 OuterObjects 中的名称匹配的正确值。 名称也可以在它的每个对象中多次出现,但正确的值将始终匹配相同的名称(即,如果在正确值中有 2 个“鲍勃”的名称,那么正确的值将是相同的)。

我有类似的东西:

outerObjects.Select(q => q.InnerObjects).Where(q => (q.small > q.big) ... then update the big with the correctValue

有没有一种好的、优雅的方式来做到这一点? 我也不想使用 forEach 语句。

我知道您不想为此使用 forEach 循环,但在这种情况下,它可能是合适的。

例如,您可以执行以下操作:

public void UpdateTheList(List<OuterObjects> theList) {
    theList.ForEach(x => {
       x.name = "John";
       x.myList.ForEach(x => {
       x.big = updateBigDbCall();
       x.small = updateSmallDbCall();
       });
    });
}

您在单独的数据库调用中更新大小,并将所有名称更新为“John”。

另一种方法是使用嵌套的 select 语句:

theList = theList.Select(e => {
   e.name = "John";
   e.myList.Select(x => {
      x.big = updateBigDbCall();
      x.small = updateSmallDbCall();
      return x;
    }).ToList();
    return e;
}).ToList();

老实说,我更喜欢将这些操作分解为单独的简短方法,每个方法做一件事。

因此,获取要更新的对象列表可能是一种方法,即从您的集合中仅选择您需要修复的那些项目。

第二种方法将迭代集合并进行任何更新。

第三种方法是进行更新所需的工作。

例如,您可以将这三个方法包装在上层方法 UpdateList 中,任何其他开发人员都可以清楚地了解代码的用途。

如果您要在 Linq 语句中修改对象(例如在您链接到的博客中显示的Select()中),那么您将度过一段糟糕的时光。

Select()投影对象,这意味着您将 map 将它们转换为新对象。

var customerNames = allCustomers.Select(c => c.Firstname + " " + c.Lastname).ToList();

如果您要滥用该方法来修改通过它的对象,那么您将不再进行纯粹的、功能性的、面向集合的编程,这不是 Linq 的目的。 这也会修改源集合中的项目,这通常不是您想要的,并且会在以后引起头疼。

Where()是从集合中过滤对象。 您要将它们减少到一个新的集合,如下所示:

var activeCustomers = allCustomers.Where(c => c.IsActive).ToList();

使用foreach()做你想做的事情的粗略、惯用的方法如下所示:

foreach (var outerObject in theList)
{
    var correction = correctValues.FirstOrDefault(c => c.Name == outerObject.Name);
    if (correction == null)
    {
        // We can't fix this outerObject
        continue;
    }
    
    // Look, Linq!
    foreach (var innerObject in outerObject.InnerObjects.Where(o => o.Small > o.Big))
    {
        // Here you're assuming that the correction will have the correct value
        innerObject.Big = correction.CorrectValue;
    }
}

现在可以肯定,您可以将其转换为带有.Where().Join()的东西,但这不会使代码更具可读性或性能,并且您仍然需要进行 object 操作来修改每个outerObject.InnerObject where Small > Big ,并且您不想在Select()中执行此操作,因此您将不得不调用.Where(...).ToList().ForEach(/* do the update */)无论如何,并且该ForEach()操作中的代码将或多或少与我上面代码中的内部foreach()中的代码完全相同。

暂无
暂无

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

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