在 Microsoft Dynamics Nav 2013 中,有一个功能可以为项目(产品)指定项目替换;但是,您可以为单个产品指定多个替换,并且从技术上讲,替换本身可以具有一个或多个替换。
我正在尝试在 PHP 中构建一个递归解决方案,它允许我获取已知的产品代码,并递归搜索项目替换以生成一维项目数组。如果这是一对一的关系(父母,孩子),这对我来说将是一项微不足道的任务,但是在任何给定的迭代中都可以有多个孩子的事实让我大吃一惊。
我的问题是,是否有人知道如何为我上面描述的情况编写递归方法?下面我将布局数据的结构方式,以便更好地理解问题:
$lineItems = array(
'XXX-0',
'XXX-1',
'XXX-3'
);
$substitutionsLookup = array(
0 => array('No_' => 'XXX-1', 'Substitute No_' => 'XXX-2'),
1 => array('No_' => 'XXX-3', 'Substitute No_' => 'XXX-4'),
2 => array('No_' => 'XXX-3', 'Substitute No_' => 'XXX-5'),
3 => array('No_' => 'XXX-5', 'Substitute No_' => 'XXX-6')
);
// Resulting product code substitutions for XXX-0
$result1 = array();
// Resulting product code substitutions for XXX-1
$result2 = array('XXX-2');
// Resulting product code substitutions for XXX-3
$result3 = array('XXX-4', 'XXX-6');
编辑(添加了我使用递归方法解决的尝试):
protected function getSubstitutions($haystack, $needle, &$results = array())
{
if (count($haystack) == 0)
{
return false;
}
$matches = array();
foreach ($haystack as $index => $check)
{
if ($check['No_'] === $needle)
{
$newHaystack = $haystack;
unset($newHaystack[$index]);
$moreMatches = $this->getSubstitutions($newHaystack, $check['Substitute No_'], $results);
if ($moreMatches === false)
{
$matches[] = $check['Substitute No_'];
}
}
}
if (count($matches))
{
foreach($matches as $match)
{
$results[] = $match;
}
}
return $results;
}
编辑(使用的最终代码,来自接受的答案):
class ItemSubstitutionService implements ServiceLocatorAwareInterface
{
public function getSubstitutions($itemNo, $noInventoryFilter = true, $recursive = true)
{
$substitutions = array();
$directSubs = $this->itemSubstitutionTable->getSubstitutionsByNo($itemNo);
if ($recursive)
{
foreach($directSubs as $sub)
{
$this->getSubstitutionsRecursive($sub, $substitutions);
}
} else {
$substitutions = $directSubs;
}
foreach($substitutions as $index => $sub)
{
$inventory = $this->itemLedgerEntryTable->getQuantityOnHand($sub->getSubstituteNo());
$sub->setInventory($inventory);
if ($noInventoryFilter)
{
if ($inventory == 0)
{
unset($substitutions[$index]);
}
}
}
return $substitutions;
}
private function getSubstitutionsRecursive(ItemSubstitution $sub, &$subs)
{
$directSubs = $this->itemSubstitutionTable->getSubstitutionsByNo($sub->getSubstituteNo());
if (empty($directSubs))
{
$subs[$sub->getSubstituteNo()] = $sub;
}
foreach($directSubs as $curSub)
{
$this->getSubstitutionsRecursive($curSub, $subs);
}
}
}