2012-11-23 34 views
1

从下面的代码中,我想过滤并希望仅获得MasterproductID = 1及其子项。通过过滤MasterproductID = 2MasterproductID = 3。 我可以知道该怎么做?谢谢你的帮助。在C#中使用过滤器表达式

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

回答

0

是否有某些原因,您的示例代码或您的解释不明显,您不能简单地使用它?

.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)) 

以实现TreeNodeattribute的最佳方法取决于你的实现细节其余的 - 我想将其封装在一个容器类有一个Map<int, TreeNode>来跟踪所有已知的节点。该图将用于构建TreeNode以设置父参考。

+0

也许查询需要是递归的输出? –

+0

如果是这样的话,目前的数据模型设计得非常差,而且确实需要进行一些重构才能使其效率和优雅。在我看来,在内存表示中添加对父对象的真实引用(即使这些内容来自SQL表格)将是最好的方法。 – SAJ14SAJ

1

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

然后:

foreach (var item in LevelIncl(list, 1)) 

这将产生用于在节点1,图4,图7,图8,图5和6