简体   繁体   English

了解递归 LINQ function

[英]Understanding Recursive LINQ function

I have the following table我有下表

ItemNumber | FirstId | SecondId | ClientId
1          | 14      | 16       | NULL
2          | 17      | 18       | 1233242323
3          | 14      | 18       | 1233242323
5          | 15      | 12       | NULL
6          | 14      | 8        | 324234252
7          | 19      | 14       | 324234252
8          | 18      | 19       | 324234252
9          | 20      | 18       | 324234252

With following Class与以下 Class

public class ClientObject
{
    public int ItemNumber { get; set; }
    public int FirstId { get; set; }
    public int SecondId { get; set; }
    public double ClientId { get; set; }

    public ClientObject()
    {

    }
}

Given the FirstId and ClientId, I want to return SecondId where no matching is found in the FirstId column.给定 FirstId 和 ClientId,我想返回在 FirstId 列中找不到匹配项的 SecondId。 Eg: Starting with FirstId as 20 ItemNumber 9), I would like to return 8 (ItemNumber 6).例如:从 FirstId 作为 20 ItemNumber 9) 开始,我想返回 8 (ItemNumber 6)。

I am trying to use a recursive function approach but not sure if it is right or if there is a better way to approach this problem.我正在尝试使用递归 function 方法,但不确定它是否正确,或者是否有更好的方法来解决这个问题。

public ClientObject GetItemRecursive(int initialId, double client)
{
    var returnThis = databaseCtxt.TableToUse
        .Where(x => x.FirstId == initialId && x.ClientId == client)
        .AsEnumerable() // updated from suggestion 
        .Select(x => GetItemRecursive(x.SecondId, x.ClientId))
        .FirstOrDefault();
    return returnThis ;
}

I have tried to set this up locally but have not been able to as this is a very very tiny part of large project, so I created the smallest examples here.我试图在本地进行设置,但由于这是大型项目中非常小的一部分,所以我在这里创建了最小的示例。

You actually need to check if the recursive call returns a null meaning there's no match and you've got to the "leaf".您实际上需要检查递归调用是否返回null意味着没有匹配并且您已经到了“叶子”。

public ClientObject GetItemRecursive(int initialId, double client)
{
    var initial = databaseCtxt.TableToUse
        .FirstOrDefault(x => x.FirstId == initialId && x.ClientId == client);
    if(initial == null) return null; 
    var child = GetItemRecursive(initial.SecondId, client);
    return child ?? initial;
}

Or you could write it without recursion或者你可以不递归地写它

public ClientObject GetItemRecursive(int initialId, double client)
{
    ClientObject parent = null;
    bool childFound = true;
    while(childFound)
    {
        var id = parent?.SecondId ?? initialId
        var child = databaseCtxt.TableToUse
            .FirstOrDefault(x => x.FirstId == id && x.ClientId == client);
        if(child == null) childFound = false;
        else parent = child;
    }

    return parent;
}

I would assume you are looking for something like this我会假设你正在寻找这样的东西

public ClientObject GetItemRecursive(int initialId, double client)
{
    return Inner(initialId, client, null);

    ClientObject Inner(int id, double d, ClientObject acc )
    {
       var current = databaseCtxt.TableToUse
         .Where(x => x.FirstId == id&& x.ClientId == d)
         .FirstOrDefault();
       if(current == null) return acc;    
       return Inner(current.SecondId, current.ClientId, current);
    }
}

This code uses C# 7.0 feature local functions fro convenience.为方便起见,此代码使用 C# 7.0 功能本地函数

So general approach is that you make have an accumulator ( acc ) which is updated on each iteration until you can't find continuation(request to db returns null), when you reach this point you return the accumulator through all nested calls.所以一般的方法是你有一个累加器( acc ),它在每次迭代时更新,直到你找不到继续(对 db 的请求返回 null),当你到达这一点时,你通过所有嵌套调用返回累加器。

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

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