如何从递归递归函数
我在我的一个需求中实现了递归。我的实际需求如下: -如何从递归递归函数
有一个主表名为库存,它有许多记录,比如说“库存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;
}
通常情况下,递归方法调用需要像中断值,这对回报进行检查,对信号递归调用结束和停止调用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;
}
HI KBO,我修改了代码。请看一下。在foreach循环中添加break不起作用。在foreach循环中的GetAllRecursiveBundle()会根据vmAllBundle List中的项目数在最终退出前被调用。对此有何想法? – user1843970
我非常惊讶你的代码可以运行。
您正在修改正在迭代的列表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?
嗨buffjape。感谢您分享最佳做法。我在Foreach Loop外面拿走了移除部分。请查看修改后的代码,并告诉我是否可以。如果你可以在退出函数之前回答多次在foreach循环中调用GetAllRecursiveBundle()的查询,那么它会很好。我已经看到,在foreach循环中的GetAllRecursiveBundle()在最终退出前基于vmAllBundle List中的项目数被调用。 – user1843970
我可以建议你运行代码,看看它是否适合你。 – buffjape
它正在为我工作,但请让我知道从编码的角度来看它是否正确。 – user1843970
是代码无限期运行?它永远不会结束吗? –
嗨德文,即使最初也没有无限的时间。我修改了代码。 – user1843970
是否必须在递归方法内完成从表中获取数据?我认为如果递归方法只接受选定的清单及其之间的关系,那么递归方法实现起来会简单得多。 – Poosh