如果子列表包含具有 Linq 的特定对象,则设置值

Set value if sublist contain specific object with Linq

我有元素列表

List<Element>() list;

Class Element 的定义如下:

public class Element
{
   public bool IsActive {get; set; }
   public string Name { get; set; }
   public List<Element> SubElements { get; set; }
}

此列表包含信息

[{
 IsActive: false;
 Name: "A";
 SubElements:
      [{
        IsActive: false;
        Name: "B";
        SubElements: null;
      },
      {
        IsActive: false;
        Name: "C";
        SubElements: null;
      }]
},
{
 IsActive: false;
 Name: "D";
 SubElements:
      [{
        IsActive: false;
        Name: "E";
        SubElements: null;
      },
      {
        IsActive: false;
        Name: "F";
        SubElements: null;
      }]
}] 

问题是如何通过SubElement名称为该结构的第一层和第二层设置IsActive为真

例如,如果我得到 "B",具有 Name = "B"; 的元素及其父元素应该具有 IsActive = true;

我知道如何用 foreach 循环来做,但是可以用 Linq 来做吗?

在不修改 Element class 的情况下,我认为使用 LINQ 无法实现您描述的行为。但是,您可以使用 List<T>.ForEach, while utilizing LINQ's Enumerable.Any<TSource>:

// for each Element e in list
list.ForEach(e =>
{
    // if any sub-Element e1 in element e has Name == "B"
    if (e.SubElements.Any(e1 => e1.Name == "B"))
    {
        // set Element e.IsActive = true
        e.IsActive = true;

        // for each sub-Element e1 in Element e, set e1.IsActive = true
        e.SubElements.ForEach(e1 => e1.IsActive = true);
    }
});

LINQ 不是为修改数据而设计的,而是为查询和转换数据而设计的。您可以使用修改后的 Elements 集创建列表的新副本:

public static List<Element> MakeActivatedList(List<Element> list, string activeName) {
    return list.Select(e => (e.Name == activeName || (e.SubElements != null && e.SubElements.Any(e1 => e1.Name == activeName))) ? new Element { IsActive = true, Name = e.Name, SubElements = (e.SubElements == null) ? null :  MakeActivatedList(e.SubElements, activeName) } : e).ToList();
}

但是如果你真的想在原始列表中设置值,你不应该使用 LINQ:

public static void SetActive(List<Element> list, string activeName) {
    foreach (var e in list) {
        if (e.Name == activeName || (e.SubElements != null && e.SubElements.Any(e1 => e1.Name == activeName)))
            e.IsActive = true;
        if (e.SubElements != null)
            SetActive(e.SubElements, activeName);
    }
}