C# 在C语言中使用过滤器表达式#

C# 在C语言中使用过滤器表达式#,c#,filtering,C#,Filtering,从下面的代码中,我想筛选并只希望获得MasterproductID=1及其子项。通过过滤MasterproductID=2和MasterproductID=3。 我可以知道怎么做吗?谢谢你的帮助 class TreeNode { public int MasterProductId; public int? ParentId; } protected void Page_Load(object sender, EventArgs e) { var list = new

从下面的代码中,我想筛选并只希望获得
MasterproductID=1
及其子项。通过过滤
MasterproductID=2
MasterproductID=3
。 我可以知道怎么做吗?谢谢你的帮助

class TreeNode
{
    public int MasterProductId;
    public int? ParentId;
}

protected void Page_Load(object sender, EventArgs e)
{
    var list = new List<TreeNode>{

        new TreeNode{ MasterProductId = 1 },
        new TreeNode{ MasterProductId = 4, ParentId = 1 },
        new TreeNode{ MasterProductId = 7, ParentId= 4 },
        new TreeNode{ MasterProductId = 5, ParentId = 1 },
        new TreeNode{ MasterProductId = 6, ParentId = 1 },

        new TreeNode{ MasterProductId = 2 },
        new TreeNode{ MasterProductId = 7, ParentId = 2 },
        new TreeNode{ MasterProductId = 8, ParentId= 7 },

        new TreeNode{ MasterProductId = 3 },

    };

    foreach (var item in Level(list, null, 0))
    {
        if (item.Value == 0)
        {
            Response.Write(String.Format("<b>MasterProductId={0}, Level={1}", item.Key, item.Value) + "</b><br />");
        }
        else
        {
            Response.Write(String.Format("MasterProductId={0}, Level={1}", item.Key, item.Value) + "<br />");
        }
    }
}

private static IEnumerable<KeyValuePair<int, int>> Level(List<TreeNode> list, int? parentId, int lvl)
{
    return list
        .Where(x => x.ParentId == parentId)
        .SelectMany(x =>
            new[] { new KeyValuePair<int, int>(x.MasterProductId, lvl) }.Concat(Level(list, x.MasterProductId, lvl + 1))
        );
}
类树节点
{
公共int主产品ID;
公共int?ParentId;
}
受保护的无效页面加载(对象发送方、事件参数e)
{
变量列表=新列表{
新树节点{MasterProductId=1},
新树节点{MasterProductId=4,ParentId=1},
新树节点{MasterProductId=7,ParentId=4},
新树节点{MasterProductId=5,ParentId=1},
新树节点{MasterProductId=6,ParentId=1},
新树节点{MasterProductId=2},
新树节点{MasterProductId=7,ParentId=2},
新树节点{MasterProductId=8,ParentId=7},
新树节点{MasterProductId=3},
};
foreach(级别中的var项(列表,空,0))
{
如果(item.Value==0)
{
Write(String.Format(“MasterProductId={0},Level={1}”,item.Key,item.Value)+“
”; } 其他的 { Write(String.Format(“MasterProductId={0},Level={1}”,item.Key,item.Value)+“
”; } } } 私有静态IEnumerable级别(列表、int?parentId、int lvl) { 返回列表 .Where(x=>x.ParentId==ParentId) .SelectMany(x=> new[]{new KeyValuePair(x.MasterProductId,lvl)}.Concat(Level(list,x.MasterProductId,lvl+1)) ); }
从您的示例代码或您的解释来看,您不能简单地使用它是有原因的吗

.Where(x => x.MasterProductId == 1 || (x.ParentId.HasValue && x.ParentId.Value == 1))

如建议的那样,如果您正在寻找递归祖先关系,而不仅仅是父关系,那么对数据结构进行一些更新将非常有助于实现这一目标

class TreeNode
{
    public int MasterProductId;
    public int? ParentId;

    private TreeNode parent; 
        // How this gets set requires other data structures, and some knowledge of
        // how you are loading the data--but this should give you the outline of an idea

    public bool HasAncestor(int referenceId, int ancestor) {

        if (!parentId.HasValue) 
        { 
            return false 
        };

        if (parentId.Value == ancestor) 
        {
            return true;
        }

        return parent.HasAncestor(ancestor);                
    }
}
然后,您将能够执行以下操作:

 .Where(x => x.MasterProductId == 1 || x.HasAncestor(1))

TreeNode
中实现父
属性的最佳方法取决于其余的实现细节——我将把它封装在一个容器类中,该容器类具有一个
映射来跟踪所有已知节点。该映射将用于构建
树节点来设置父引用。

从示例代码或您的解释来看,有什么原因不能简单地使用它吗

.Where(x => x.MasterProductId == 1 || (x.ParentId.HasValue && x.ParentId.Value == 1))

如建议的那样,如果您正在寻找递归祖先关系,而不仅仅是父关系,那么对数据结构进行一些更新将非常有助于实现这一目标

class TreeNode
{
    public int MasterProductId;
    public int? ParentId;

    private TreeNode parent; 
        // How this gets set requires other data structures, and some knowledge of
        // how you are loading the data--but this should give you the outline of an idea

    public bool HasAncestor(int referenceId, int ancestor) {

        if (!parentId.HasValue) 
        { 
            return false 
        };

        if (parentId.Value == ancestor) 
        {
            return true;
        }

        return parent.HasAncestor(ancestor);                
    }
}
然后,您将能够执行以下操作:

 .Where(x => x.MasterProductId == 1 || x.HasAncestor(1))

TreeNode
中实现父
属性的最佳方法取决于其余的实现细节——我将把它封装在一个容器类中,该容器类具有一个
映射来跟踪所有已知节点。该映射将用于构建
TreeNode
以设置父引用。

级别
方法已经几乎完全满足了您的需要。如果修改了
foreach
以指定1的
ParentId

foreach (var item in Level(list, 1, 0))
然后它将为节点4、7、8、5和6生成输出。也就是说,它返回节点的后代

如果还希望包含指定的父节点,则只需将其连接到结果列表中。例如:

private static IEnumerable<KeyValuePair<int, int>> LevelIncl(
                 List<TreeNode> list, int parentId)
{
    return new[] {new KeyValuePair<int, int>(parentId, 0)}
              .Concat(Level(list, parentId, 1));
}

这将为节点1、4、7、8、5和6生成输出。

Level
方法已经几乎完全满足了您的需求。如果修改了
foreach
以指定1的
ParentId

foreach (var item in Level(list, 1, 0))
然后它将为节点4、7、8、5和6生成输出。也就是说,它返回节点的后代

如果还希望包含指定的父节点,则只需将其连接到结果列表中。例如:

private static IEnumerable<KeyValuePair<int, int>> LevelIncl(
                 List<TreeNode> list, int parentId)
{
    return new[] {new KeyValuePair<int, int>(parentId, 0)}
              .Concat(Level(list, parentId, 1));
}

这将为节点1、4、7、8、5和6生成输出。

也许查询需要递归?如果是这种情况,当前的数据模型设计得非常糟糕,因此需要进行一些重构,以使其具有合理的效率和优雅性。在我看来,在内存表示中添加对父级的真正引用(即使这些内容来自SQL表)将是最好的方法。也许查询需要递归?如果是这样的话,当前的数据模型设计得非常糟糕,而且确实需要进行一些重组,以使其具有合理的效率和优雅。在我看来,在内存表示中添加对父级的真正引用(即使这些内容来自SQL表)是最好的方法。