2016-07-18 4 views
0

Я пишу программу на PHP (так как она будет сопровождать веб-код для системы математической градации), и мне нужно создать массив строк и массивов. В частности, я хочу, чтобы преобразовать что-то вродеPHP массив строк и массивов

((4)+((5)*(pi)))-((9)*(sqrt(3))) 

в

[["4", ["5", "pi", "*"], "+"], ["9", ["3", "sqrt"], "*"], "-"] 

, который является массивом форматирования обратной-польской записи. С этим я бы оценил для коммутативности по операторам сравнение правильного, сохраненного ответа на ответ ученика. Тем не менее, я не могу сделать это на PHP с многомерными массивами из-за неравномерности строк.

Если есть способ сделать это с помощью строк, это будет еще более полезно (поскольку я планирую хранить результаты в базе данных SQL), но для этого я, вероятно, мог бы использовать serialize().

Спасибо за любую помощь.

EDIT: Я думаю, что у меня это получилось. По-видимому, использование коротких записей в массиве вызвало проблему. Старая array() обозначения, кажется, функционирует должным образом, например, так:

array(array("4", array("5", "pi", "*"), "+"), array("9", array("3", "sqrt"), "*"), "-") 

и сериализованная нотация (для хранения в базе данных) составляет:

a:3:{i:0;a:3:{i:0;s:1:"4";i:1;a:3:{i:0;s:1:"5";i:1;s:2:"pi";i:2;s:1:"*";}i:2;s:1:"+";}i:1;a:3:{i:0;s:1:"9";i:1;a:2:{i:0;s:1:"3";i:1;s:4:"sqrt";}i:2;s:1:"*";}i:2;s:1:"-";}. 
+0

Почему 'sqrt (3)' не разбивается на '[3," sqrt "'] '? – trincot

+1

Поскольку вы используете RPN, вам не нужно ничего группировать. Вы должны иметь возможность использовать простой плоский массив. – NovaDenizen

+0

Это может вам помочь: https://github.com/andig/php-shunting-yard – nikoskip

ответ

0

Вот функция, которая будет выполнять преобразование из строки в гнездовой массив:

function convert($string) { 
    function nest(&$base) { 
     $result = []; 
     while (($ch = array_shift($base)) !== null) { 
      if ($ch === ')') break; 
      $result[] = $ch === '(' ? nest($base) : $ch; 
     } 
     if (count($result) < 2) return reset($result); 
     // Move operator to the end of the array: 
     $result[] = array_splice($result, -2, 1)[0]; 
     return $result; 
    } 
    // split string into parts, where each bracket is a separate part 
    $base = preg_split("/([()])/", $string, 0, PREG_SPLIT_DELIM_CAPTURE 
              + PREG_SPLIT_NO_EMPTY); 
    // recursively build nested postfix structure 
    return nest($base); 
} 

Вы назвали бы это так:

$result = convert($string); 

Для ввода пробы, представленной в этом вопросе, то выход:

array (
    array (
    '4', 
    array (
     '5', 
     'pi', 
     '*', 
    ), 
    '+', 
), 
    array (
    '9', 
    array (
     '3', 
     'sqrt', 
    ), 
    '*', 
), 
    '-', 
) 

Обратите внимание, что функция sqrt также separa ted как функция постфикса.

Посмотрите, как работает на eval.in.

0

Я не вижу, что проблема с построением этого массива динамически. Например, это работает (не постфикса):

$test_array = array(
        array(
         "4", 
         array(
          "5", 
          "pi", 
          "*" 
         ), 
         "+" 
        ), 
        array(
         "9", 
         array(
          "3", 
          "sqrt" 
         ), 
         "*" 
        ), 
        "-" 
      ); 

var_dump($test_array); 

Так что делает это динамически с помощью алгоритма должен вести себя подобным образом, чтобы делать это (конечно порядок добавления элемента зависит от алгоритма):

$test_array2 = array(); 
$test_array2[] = array(); 
$test_array2[] = array(); 
$test_array2[] = "-"; 
$test_array2[1][] = "9"; 
$test_array2[1][] = array(); 
$test_array2[1][1][] = "3"; 
$test_array2[1][1][] = "sqrt"; 
$test_array2[1][] = "*"; 
$test_array2[0][] = "4"; 
$test_array2[0][] = array(); 
$test_array2[0][1][] = "5"; 
$test_array2[0][1][] = "pi"; 
$test_array2[0][1][] = "*"; 
$test_array2[0][] = "+"; 

var_dump($test_array2); 

Оба примера выше имеют одинаковый выход.

0

Для универсальности и универсальности вы также можете использовать ассоциативный массив, в качестве индексов, своих ролей, как в одном из {operand1, operand2, and operator}. Действительно, любое математическое выражение, указанное выше, может иметь шаблон: «operand1 operator operand2», каким бы сложным они ни были в конце.

Пример:

5.пи будет

array('op1'=>5, 'op'=>'*', 'opd2'=>'pi'); 

SQRT (3) будет

array('op1' => 3, 'op' => 'sqrt', 'opd2' => null); // since sqrt is a unary function 

и так далее ...

Таким образом, модель будет расширяемой, вы бы извлечь выгоду из функций массивов семейства относительно индексы, не беспокоясь о порядках членов массива, а синтаксический анализатор будет, ИМХО, намного проще писать и, по крайней мере, быть прочитанным человеком.

Смежные вопросы