2017-08-11 180 views
0

我在我的一个需求中实现了递归。我的实际需求如下: -如何从递归递归函数

有一个主表名为库存,它有许多记录,比如说“库存A”,“库存B”,“库存C”。

还有一个表叫做库存包它链接一个库存与其他。所以库存包表具有两列: - 代表源库存Id和目标库存ID的TI & TI。

Record Ex。

SI TI

A B

B C

在,如果我点击任何库存,则关联的库存也应取了我的要求。

像这里一样,如果我点击B然后A & C应该被取出。我使用以下递归方法来获得要求: -

List<Guid> vmAllBundle = new List<Guid>(); 
List<Guid> vmRecursiveBundle = new List<Guid>(); 
List<Guid> processedList = new List<Guid>(); 

public List<Guid> GetAllRecursiveBundle(Guid invId, Guid originalInvId) 
     {      
      List<Guid> vmInvSrcBundleList = GetSourceInventory(invId); //Fetch to get All Related Source Inventories 
      List<Guid> vmInvTarBundleList = GetTargetInventory(invId); //Fetch to get All Related Target Inventories 

      vmAllBundle.AddRange(vmInvSrcBundleList); 
      vmAllBundle.AddRange(vmInvTarBundleList);   

      if (vmAllBundle.Contains(originalInvId)) 
       vmAllBundle.Remove(originalInvId); 
      vmAllBundle = vmAllBundle.Distinct().ToList(); 

      vmRecursiveBundle = vmAllBundle.ToList().Except(processedList).ToList(); 

      foreach (Guid vmInvBundle in vmRecursiveBundle) 
      { 
       vmRecursiveBundle.Remove(vmInvBundle); 
       processedList.Add(vmInvBundle); 
       GetAllRecursiveBundle(vmInvBundle, originalInvId); 

       if (vmRecursiveBundle.Count == 0) 
        return vmAllBundle; 
      } 

      return null; 
     } 

我能够使用此方法获取数据,但我在返回时遇到问题。

当我返回时,它调用GetAllRecursiveBundle()并使用foreach循环并继续调用,直到vmAllBundle中的所有项都完成为止。之后它退出递归。

这是我的新东西,所以张贴问题,问这是正常行为还是一些代码逻辑必须改变。

修改代码

public List<Guid> GetAllRecursiveBundle(Guid invId, Guid originalInvId) 
     { 
      if (vmRecursiveBundle.Count > 0) 
       vmRecursiveBundle.Remove(invId); 

      List<Guid> vmInvSrcBundleList = GetSourceInventory(invId); //Fetch to get All Related Source Inventories 
      List<Guid> vmInvTarBundleList = GetTargetInventory(invId); //Fetch to get All Related Target Inventories 

      vmAllBundle.AddRange(vmInvSrcBundleList); 
      vmAllBundle.AddRange(vmInvTarBundleList);   

      if (vmAllBundle.Contains(originalInvId)) 
       vmAllBundle.Remove(originalInvId); 
      vmAllBundle = vmAllBundle.Distinct().ToList(); 

      vmRecursiveBundle = vmAllBundle.ToList().Except(processedList).ToList(); 

      foreach (Guid vmInvBundle in vmRecursiveBundle) 
      {     
       processedList.Add(vmInvBundle); 
       GetAllRecursiveBundle(vmInvBundle, originalInvId); 

       if (vmRecursiveBundle.Count == 0) 
        break; 
      } 

      return vmAllBundle; 
     } 
+0

是代码无限期运行?它永远不会结束吗? –

+0

嗨德文,即使最初也没有无限的时间。我修改了代码。 – user1843970

+0

是否必须在递归方法内完成从表中获取数据?我认为如果递归方法只接受选定的清单及其之间的关系,那么递归方法实现起来会简单得多。 – Poosh

回答

1

通常情况下,递归方法调用需要像中断值,这对回报进行检查,对信号递归调用结束和停止调用reursive方法。我不完全了解你的代码,因此这里是一个例子:

private string SearchFileRecursive(string directory, string fileToFind) 
{ 
    string filePath = null; 

    string[] files = Directory.GetFiles(directory); 

    string foundFile = files.FirstOrDefault(file => (0 == string.Compare(Path.GetFileName(file), fileToFind, true))); 

    if(string.IsNullOrEmpty(foundFile)) 
    { // not found 
    string[] subDirectories = Directory.GetDirectories(directory); 
    foreach(string subDirectory in subDirectories) 
    { 
     filePath = SearchFileRecursive(subDirectory, fileToFind); 
     if(!string.IsNullOrEmpty(filePath)) // found 
     break; 
    } 
    } 
    else 
    { // found 
    filePath = Path.Combine(directory, foundFile); 
    } 

    return filePath; 
} 
+0

HI KBO,我修改了代码。请看一下。在foreach循环中添加break不起作用。在foreach循环中的GetAllRecursiveBundle()会根据vmAllBundle List中的项目数在最终退出前被调用。对此有何想法? – user1843970

1

我非常惊讶你的代码可以运行。

您正在修改正在迭代的列表foreach - 通常会引发异常。

foreach (Guid vmInvBundle in vmRecursiveBundle) 
{ 
    vmRecursiveBundle.Remove(vmInvBundle); // **CRASHES HERE** 
} 

修改收集由foreach正在迭代是不允许的,并会被认为即使它被允许的(因为它经常导致错误)不好的做法。

你可以改变一个for循环,有没有这样的顾虑:

for (int i = 0; i < vmRecursiveBundle.Count; i++) 
{ 
    Guid vmInvBundle = vmRecursiveBundle[i]; 

    vmRecursiveBundle.Remove(vmInvBundle); // **NO CRASH** 

    i--;  // counteracts the i++ so the next Guid is not skipped 
} 

有关进一步详情,请参阅What is the best way to modify a list in a 'foreach' loop?

+0

嗨buffjape。感谢您分享最佳做法。我在Foreach Loop外面拿走了移除部分。请查看修改后的代码,并告诉我是否可以。如果你可以在退出函数之前回答多次在foreach循环中调用GetAllRecursiveBundle()的查询,那么它会很好。我已经看到,在foreach循环中的GetAllRecursiveBundle()在最终退出前基于vmAllBundle List中的项目数被调用。 – user1843970

+0

我可以建议你运行代码,看看它是否适合你。 – buffjape

+0

它正在为我工​​作,但请让我知道从编码的角度来看它是否正确。 – user1843970