PHP: упростить с помощью алгоритма? - PullRequest
2 голосов
/ 15 июня 2010

Вот фрагмент кода PHP, который я считаю не очень «красивым», я уверен, что можно упростить его с помощью for или чего-то еще. Я пытаюсь найти и алгоритм, который бы работал для этого, но я не могу понять, пожалуйста, помогите мне.

Вот код:

if(isset($four))
{
 if(isset($navi[$one][$two][$three][$four])) echo "/content/" . $one . "/" . $two . "/" . $three . "/" .$four . ".php";
 else echo "error";
}
else if(isset($three))
{
 if(isset($navi[$one][$two][$three]))  echo "/content/" . $one . "/" . $two . "/" . $three . ".php";
 else echo "error";
}
else if(isset($two))
{
 if(isset($navi[$one][$two])) echo "/content/" . $one . "/" . $two . ".php";
 else echo "error";
}
else if(isset($one))
{
 if(isset($navi[$one]))echo "/content/" . $one . ".php";
 else echo "error";
}
else
{
 echo "error";
}

Спасибо!

Ответы [ 4 ]

2 голосов
/ 15 июня 2010

Обновлено, проверено:

$parts = array($one, $two, $three, $four);
$reversed = array_reverse($parts);

function getPath($ret, $n) {
    global $parts;
    foreach (range(0, $n) as $i) {
        $ret = $ret[$parts[$i]];
    }
    return $ret;
}

$error = false;
foreach (range(0, count($reversed)) as $i) {
    if (!$reversed[$i]) {
        unset($reversed[$i]);
        continue;
    }

    if (!getPath($navi, count($parts) - $i - 1)) {
        $error = true;
        break;
    }
}

if ($error) {
    echo "error!";
} else {
    echo "/content/" . implode("/", array_reverse($reversed)) . ".php";
}
0 голосов
/ 15 июня 2010

Рекурсивное решение, для полноты:

function navi_recurse(&$navi, &$steps, $i = 0) {
  if ($i < count($steps) - 1) {
    $step = $steps[$i];
    if ( isset($navi[$step]) )
      return navi_recurse($navi[$step], $steps, $i+1);
    else
      return "error\n";
  } 
  return '/content/'.implode('/', $steps).'.php';
}

Звоните так:

$steps = array($one, $two, $three, $four);
echo navi_recurse($navi, $steps);
0 голосов
/ 15 июня 2010

Я думаю, что с вашим кодом есть более глубокие проблемы. Но решить именно эту проблему - есть мое предположение:

$urls = array();
$tempNavi = $navi;
foreach (array('one', 'two', 'three', 'four') as $var) {
    if (!isset($$var) || !isset($tempNavi[$$var]))
        break;
    $tempNavi = $tempNavi[$$var];
    $urls[] = $$var;
}

if ($urls) {
    echo '/content/' . implode('/', $urls);
} else {
    echo 'error';
}
0 голосов
/ 15 июня 2010

Проблема в том, что вы используете isset(foo), что затрудняет помещение переменных в массив. Если будет проверена длина переменной, используйте:

$parts = array_reverse(array($one,$two,$three,$four));
foreach ($parts as $i => $value) 
    if(strlen($value)==0) 
        unset($array[$i]);
$final = join('/',parts);
if(isset($navi[$final])) echo "/content/" . $final . ".php";
else echo "\nerror\n\n\n";

Но для этого потребуется изменить конструкцию $ navi, чтобы она выглядела как

$navi['foo/bar/baz'] = "someval";

вместо

$navi['foo']['bar']['baz'] = "someval";

, потому что мы будем использовать сцепленную строку $final для поиска в $ isset. В противном случае единственный маршрут - это динамически генерируемый php, что ужасно.

Не могли бы вы структурировать ваши данные по-другому? Циклы для измерений массива не очень приятны, тогда как приведенный выше плоский список гораздо проще выполнить.

...