Linq将外部联接留在同一列表中以查找叶节点

本文关键字:列表 叶节点 查找 外部 Linq | 更新日期: 2023-09-27 17:58:32

我在内存中有一个List<TreeNode>。是否可以使用linq来选择所有的叶节点?

SQL看起来像这样:

SELECT      
    t1.Name
FROM 
    Tree t1 
    LEFT JOIN Tree t2 
        ON t1.UserId = t2.ParentId  
WHERE 
    t2.UserId is null

我得到的最接近的是(我仍然需要过滤掉null):

                       var test = from t1 in list
                       join t2 in list
                       on t1.UserId equals t2.ParentId into g                   
                       from result in g.DefaultIfEmpty()          
                       select new { 
                       t1.Name
                       };

它在不使用where子句的情况下生成正确的sql(在linqpad中测试时)。如果我试图在t2==null的位置过滤结果,我就无法访问我选择的匿名对象的t2。我需要创建列表的副本并加入其中吗?

Linq将外部联接留在同一列表中以查找叶节点

编辑:好吧,我以前误解了。所以你基本上是在列表中没有元素t2的项目(t1)后面,比如t1.UserId == t2.ParentId?在这种情况下,我建议您使用:

我怀疑你想要:

var test = from t1 in list
           join t2 in list
              on t1.UserId equals t2.ParentId into g
           where !g.Any()
           select t1.Name;

请注意,我在这里没有使用匿名类型,因为您只选择了一个值。

另一种选择是:

var parents = new HashSet<Guid>(list.Where(x => x.ParentId != null)
                                    .Select(x => x.ParentId.Value));
var query = list.Where(t1 => !parents.Contains(t1.UserId));

试试这个:

var test = from t1 in list
           join t2 in list
           on t1.UserId equals t2.ParentId into g                   
           from result in g.DefaultIfEmpty()          
           where t2.UserId == null
           select new { 
               t1.Name
           };