разбить строку на массив ключ => значение в php - PullRequest
2 голосов
/ 19 апреля 2010
+2-1+18*+7-21+3*-4-5+6x29

Приведенная выше строка является примером вида строки, которую я пытаюсь разбить на массив key => value или что-то подобное. Строка используется для представления макета различных классов на странице с тремя столбцами сайта интрасети, которую пользователь может редактировать с помощью перетаскивания. Эта строка сохраняется в файле cookie для использования при следующем посещении.

Числа представляют идентификатор класса, а -, + и x представляют состояние класса (свернуто, развернуто или скрыто), * представляет разрыв столбца.

Я могу легко разбить это на столбцы, используя explode, который дает и массив с 3 $ key => $ value ассоциациями.

например.

$column_layout = array( [0] => '+2-1+18' , [1] => '+7-21+3' , [2] => '-4-5+6x29' )

Затем мне нужно разделить это на различные классы, сохраняя статус и идентификатор вместе. Поскольку различные классы и статусы будут меняться от пользователя к пользователю и сколько их будет в каждом столбце, мне нужно будет делать все это автоматически.

например.

$column1 = array( '+' => 2 , '-' => 1 , '+' => 18 )
...

или

$column1 = array( array( '+' , 2 ) , array( '-' , 1 ) , array( '+' , 18 ) )
...

Я не могу полностью разобраться в этом, и какой лучший способ сделать это, так что любая помощь будет высоко ценится.

1 Ответ

7 голосов
/ 19 апреля 2010

Первый explode() массив с разделителем *

Затем вы можете использовать preg_match_all для сопоставления каждого элемента в разобранном массиве. Примерно так работает с вашим примером ввода.

$layout = explode('*', $input);
$columns = array();
foreach ( $layout as $item ){
    $parts = array();

    //matches either a -, x or + followed by one or more digits
    preg_match_all('/([+-x])(\d+)/', $item, $matches, PREG_SET_ORDER);

    foreach ( $matches as $match){ 
        //match[1] hold the + or -, match[2] holds the digits
        $parts[] = array($match[1], $match[2]);
    }
    $columns[] = $parts;
}

Вывод из вашего примера заканчивается так:

array(
     array( array('+', '2'), array('-', '1'), array('+', '18') ),
     array( array('+', '7'), array('-', '21'), array('+', '3') ),
     //etc
);

В PHP 5.3 вы можете использовать что-то вроде этого (не проверено). Основное отличие состоит в том, что внутренний цикл был заменен на array_map, что устраняет необходимость в большом количестве строк кода. (Карта массивов применяет функцию к каждому элементу в массиве и возвращает преобразованный массив). PHP 5.3 требуется для хорошего синтаксиса закрытия

$layout = explode('*', $input);
$columns = array();
foreach ( $layout as $item ){
    preg_match_all('/([+-x])(\d+)/', $item, $matches, PREG_SET_ORDER);
    $columns[] = array_map( function($a){ return array($a[1], $a[2]); },
                            $matches);
}

Вы также можете полностью удалить петли:

$innerMatch = function($item){
    preg_match_all('/([+-x])(\d+)/', $item, $matches, PREG_SET_ORDER);
    return array_map( function($a){ return array($a[1], $a[2]); },
                      $matches);
};
$columns = array_map($innerMatch, explode('*', $input));

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


Больше объяснений

По просьбе @ Кристофер Альтман

Единственный новый бит в версии PHP 5.3 - это:

array_map(
          function($a){ return array($a[1], $a[2]); },
          $matches
);

Немного расширив и изменив его (как пример)

//bind an anonymous function to the variable $func
$func = function($a){
    return $a*$a; 
}; 
//$func() now calls the anonymous function we have just defined

//then we can call it like so:
$result = array_map($func, $myArray);

Так что, если $myArray определено как

array(1,2,3,4);

Когда он запускается через функцию отображения массива, вы можете думать о ней как о преобразовании в

array(func(1),func(2),func(3),func(4));

Но поскольку PHP не является ленивым языком , все функции оцениваются, как только они встречаются, поэтому массив возвращается из array_map как:

array(2, 4, 9, 16)

В реальном коде preg_match_all возвращает массив совпадений (где совпадения являются массивами). Поэтому все, что я делаю, это беру массив и на каждое совпадение применяю функцию, которая преобразует совпадение в другой массив в требуемом формате.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...