php preg_split split string conditionally - php

I need to split the following
$str = 'min(5,6,7,88),email'
$str= 'min(5,6,7,88),!email,max(6,5),alpha_numeric,required'//other possibilities
so it returns an array like so:
array(
[0]=>array(
[0]=>'min',
[1]=>array(5,6,7,88)
)
[1]=>array(
[0]=>'email'
)
)
is this possible ? btw email and min could be anything really , aswell as 5 6 7 88

I think preg_match is best suited for this particular case. However, preg_match alone cannot format the output as you want it.
preg_match('/(\w+)\(([0-9,]+)\),(\w+)+/', $str, $values);
$output = array(
array($values[1], explode(',', $values[2])),
array($values[3]),
);

Given the following:
$test = "min(5,6,7,88),email";
$_ = null;
if (preg_match('/^(?<first>\w+)\((?<array>(?:[0-9]+\x2C*)+)\)\x2C(?<last>\w+)$/',$test,$_))
{
$result = Array(
Array($_['first'],explode(',',$_['array'])),
Array($_['last'])
);
print_r($result);
}
Renders the following result:
Array
(
[0] => Array
(
[0] => min
[1] => Array
(
[0] => 5
[1] => 6
[2] => 7
[3] => 88
)
)
[1] => Array
(
[0] => email
)
)

function parse($str) {
$str = str_replace(array('(',')'),"0x00",$str);
$strArray = explode("0x00",$str);
$tokens = array();
$tokenRef = 0;
foreach($strArray as $tokenID => $tokenValue) {
if (($tokenID % 2) == 1) {
--$tokenRef;
$tokens[$tokenRef++][1] = '('.$tokenValue.')';
} else {
$tokenList = explode(",",$tokenValue);
foreach($tokenList as $token) {
if ($token != '') {
$tokens[$tokenRef++][0] = $token;
}
}
}
}
return $tokens;
}
$str = 'min(5,6,7,88),email';
$split = parse($str);
echo '<pre>';
var_dump($split);
echo '</pre>';
echo '<br />';
$str = 'min(5,6,7,88),!email,max(6,5),alpha_numeric,required';
$split = parse($str);
echo '<pre>';
var_dump($split);
echo '</pre>';
echo '<br />';
Gives
array(2) {
[0]=>
array(2) {
[0]=>
string(3) "min"
[1]=>
string(10) "(5,6,7,88)"
}
[1]=>
array(1) {
[0]=>
string(5) "email"
}
}
and
array(5) {
[0]=>
array(2) {
[0]=>
string(3) "min"
[1]=>
string(10) "(5,6,7,88)"
}
[1]=>
array(1) {
[0]=>
string(6) "!email"
}
[2]=>
array(2) {
[0]=>
string(3) "max"
[1]=>
string(5) "(6,5)"
}
[3]=>
array(1) {
[0]=>
string(13) "alpha_numeric"
}
[4]=>
array(1) {
[0]=>
string(8) "required"
}
}

Related

Recursive Nested Navigation with PHP

I know this is asked a lot, but I can't get it to work correctly.
What I have
A PHP function that get's the page id (fk_page).
Inside this function the same function is called to look for child pages.
My Database looks like this:
The PHP Code looks like this:
private function createNav($parent = 0, $sub = false) {
// *!* Create Nav
$getNavPage = $this->model->loadNav($parent); // array of menu items (fk_page) that have $parent as parent.
$NavPage = 0;
foreach ($getNavPage as $getPage) {
$NavPage = intval($getPage["fk_page"]);
$subnav = $this->createNav($NavPage, true); // get childs (recursive loop) and save fk_page in $subnav
if($sub === false) $this->navArr[$parent][] = $NavPage;
else $this->navArr[$parent][][] = $NavPage;
}
return $NavPage;
}
The model does the following
public function loadNav($parent) {
$stmt = $this->pdo->prepare("SELECT fk_page FROM nav WHERE fk_parentpage = " . $parent . ";");
$stmt->execute();
return $stmt->fetchAll();
}
Now the result is an array that looks like this
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
[2]=>
array(1) {
[0]=>
array(1) {
[0]=>
int(4)
}
}
[3]=>
array(2) {
[0]=>
array(1) {
[0]=>
int(5)
}
[1]=>
array(1) {
[0]=>
int(6)
}
}
}
What I would like to have as a result:
array(3) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
array(1) {
[0]=>
array(1) {
[0]=>
int(4)
}
}
[3]=>
array(2) {
[0]=>
array(1) {
[0]=>
int(5)
}
[1]=>
array(1) {
[0]=>
int(6)
}
}
}
}
I believe that the createNav() must run before the array element is written (or even inside the array $this->NavArr), but I wasn't really succesfull.
Here is an example that uses local data but mimics what you're trying to do:
$data_array = array(
0 => array(1, 2, 3)
, 2 => array(4)
, 3 => array(5, 6)
);
function get_kids($id = 0) {
global $data_array;
if(isset($data_array[$id])) {
return $data_array[$id];
}
else {
return array();
}
}
function create_navigation($parent_id = 0) {
// Check for children
$children_array = get_kids($parent_id);
// No children - just return the parent
if (empty($children_array)) {
return $parent_id;
}
// Children!
foreach ($children_array as $key => $child_id) {
$children_array[$key] = create_navigation($child_id);
}
return array($parent_id => $children_array);
}
echo '<pre>';
$nav = create_navigation(0);
var_dump($nav);
print_r($nav);
echo '</pre>';
The $data_array is used instead of your database.
The get_kids function is your loadNav method.
The create_navigation function is your createNav method.
This produces a var_dump:
array(1) {
[0]=>
array(3) {
[0]=>
int(1)
[1]=>
array(1) {
[2]=>
array(1) {
[0]=>
int(4)
}
}
[2]=>
array(1) {
[3]=>
array(2) {
[0]=>
int(5)
[1]=>
int(6)
}
}
}
}
And a print_r:
Array
(
[0] => Array
(
[0] => 1
[1] => Array
(
[2] => Array
(
[0] => 4
)
)
[2] => Array
(
[3] => Array
(
[0] => 5
[1] => 6
)
)
)
)
The problem with your original code is you were assigning IDs to the class variable $this->navArr instead of using recursion to return the child elements ($subnav).

How can I pull multiple variable values from a string (PHP)

For example:
$string = "AND (pr.StatusCode <> 'U') AND ((pr.pkBrand = 9) OR (pr.pkBrand = 70)) AND ((pr.pkCategory = 55) OR (pr.pkCategory = 56)) AND (pr.StatusCode <> 'D')";
I would need to pull the values associate with pkBrand i.e. 9 & 70 to push into an array for use elsewhere and the values of pkCategory i.e. 55 & 56 into a separate array again for use elsewhere.
How can I do this please.
Maybe you can do something like this:
$string = "AND (pr.StatusCode <> 'U') AND ((pr.pkBrand = 9) OR (pr.pkBrand = 70)) AND ((pr.pkCategory = 55) OR (pr.pkCategory = 56)) AND (pr.StatusCode <> 'D')";
preg_match_all("/pr.pkBrand = (\d+)|pr.pkCategory = (\d+)/", $string, $matches, PREG_SET_ORDER);
The $matches array will look like this:
array(4) {
[0] =>
array(2) {
[0] =>
string(14) "pr.pkBrand = 9"
[1] =>
string(1) "9"
}
[1] =>
array(2) {
[0] =>
string(15) "pr.pkBrand = 70"
[1] =>
string(2) "70"
}
[2] =>
array(3) {
[0] =>
string(18) "pr.pkCategory = 55"
[1] =>
string(0) ""
[2] =>
string(2) "55"
}
[3] =>
array(3) {
[0] =>
string(18) "pr.pkCategory = 56"
[1] =>
string(0) ""
[2] =>
string(2) "56"
}
}
Then you can extract the values you want from this.
this is much less concise but it aims to work regardless of the field name:
<?php
$string = "AND (pr.StatusCode <> 'U') AND ((pr.pkBrand = 9) OR (pr.pkBrand = 70)) AND ((pr.pkCategory = 55) OR (pr.pkCategory = 56)) AND (pr.StatusCode <> 'D')";
$newString=trim(str_replace(')','',str_replace('(','',str_replace('OR','',str_replace('AND','',$string)))));
$tab=explode('pr.',$newString);
foreach($tab as $value) {
$value=trim(str_replace(' ','',str_replace('\'','',$value)));
$tab2[]=$value;
}
/*echo '<pre>';
var_dump($tab2);
echo '</pre>';*/
$operators=['!=','<>','<','>','='];
foreach ($tab2 as $index=>$value) {
foreach ($operators as $operator) {
$found=0;
$explode=explode($operator,$value);
if (count($explode)==1) {}//not the good one
else {
$found=1;
break;
}
}
if ($found==1) $newTab[$explode[0]][$index]=$explode[1];
}
echo '<pre>';
var_dump($newTab);
echo '</pre>';
?>
Will give you :
array(3) {
["StatusCode"]=>
array(2) {
[1]=>
string(1) "U"
[6]=>
string(1) "D"
}
["pkBrand"]=>
array(2) {
[2]=>
string(1) "9"
[3]=>
string(2) "70"
}
["pkCategory"]=>
array(2) {
[4]=>
string(2) "55"
[5]=>
string(2) "56"
}
}

Handle only the dates of an array

How do I list only dates from an array.
Use this code:
do {
$integrantes[] = $row_rs['integrantes'];
} while ($row_rs = mysql_fetch_assoc($rs));
echo '<pre>';
print_r($integrantes);
echo '</pre>';
result:
Array
(
[0] => 2:2014-08-13,4:2014-08-13,6:2014-08-13,7:2014-08-13
[1] => 3:2014-08-13,5:2014-08-13,6:2014-08-13
)
One way to do it:
$integrantes = array(
'2:2014-08-13,4:2014-08-13,6:2014-08-13,7:2014-08-13',
'3:2014-08-13,5:2014-08-13,6:2014-08-13'
);
$result = array();
foreach($integrantes as $delimited) {
$records = explode(',', $delimited);
foreach ($records as $record) {
list($id, $date) = explode(':', $record);
$result[] = $date;
}
}
var_dump($result);
Output:
array(7) {
[0]=>
string(10) "2014-08-13"
[1]=>
string(10) "2014-08-13"
[2]=>
string(10) "2014-08-13"
[3]=>
string(10) "2014-08-13"
[4]=>
string(10) "2014-08-13"
[5]=>
string(10) "2014-08-13"
[6]=>
string(10) "2014-08-13"
}
Here is Codepad demo
Try this
while ($row_rs = mysql_fetch_assoc($rs)){
preg_match_all('/\d{4}\-\d{2}-\d{2}/', $row_rs['integrantes'], $matches);
$integrantes = array_merge($integrantes, $matches[0]);
}

Getting all values into single array

I have array like the following
Array ( [0] => Array ( [0] => 5 ) [1] => Array ( [0] => 6 [1] => 7 ) )
Now I want only values of this two dimensional array
The result should be array(5,6,7)
Bit of a hack/neat trick depending on how you look at it ;)
$result = call_user_func_array('array_merge', $a);
You're looking for array_values() which returns an array of all array values, sans-keys.
http://php.net/manual/en/function.array-values.php
Update:
Alternatively for an already multi-dimensional array, you can use the following recursive function (borrowed from http://davidwalsh.name/flatten-nested-arrays-php):
function array_flatten($array,$return)
{
for($x = 0; $x <= count($array); $x++)
{
if(is_array($array[$x]))
{
$return = array_flatten($array[$x],$return);
}
else
{
if($array[$x])
{
$return[] = $array[$x];
}
}
}
return $return;
}
Something like this
array_merge($a[0], $a[1]);
function flattenArray($array) {
$flattened = array();
foreach($array as $value) {
if (is_array($value)) {
$flattened = array_merge($flattened, flattenArray($value));
} else {
$flattened[] = $value;
}
}
return $flattened;
}
$array = array(1, array(2, 3), array(4, array(5, 6)));
var_dump($array, flattenArray($array));
Output
array(3) {
[0]=>
int(1)
[1]=>
array(2) {
[0]=>
int(2)
[1]=>
int(3)
}
[2]=>
array(2) {
[0]=>
int(4)
[1]=>
array(2) {
[0]=>
int(5)
[1]=>
int(6)
}
}
}
array(6) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
[5]=>
int(6)
}
CodePad.
$result = array();
foreach($parentArray as $pa)
{
if(is_array($pa))
$result= array_merge($result, $pa);
else
$result[] = $pa;
}
Use $result.

PHP array_merge_recursive with numeric keys

So I'm suppose to build a multidimensional array dynamically from a text file, and everything works perfectly except that the numeric keys are screwing me over...
The text file looks something like this:
a=1
b.c=2
b.d.0.e=3
b.d.0.f=4
b.d.1.e=5
b.d.1.f=6
As the array_merge_recursive doesn't work with numeric keys, the output is like:
array(2) {
["a"]=>
string(3) "1"
["b"]=>
array(2) {
["c"]=>
string(3) "2"
["d"]=>
array(4) {
[0]=>
array(1) {
["e"]=>
string(9) "3"
}
[1]=>
array(1) {
["f"]=>
string(4) "4"
}
[2]=> array(1) {
["e"]=>
string(8) "5"
}
[3]=>
array(1) {
["f"]=>
string(9) "6"
}}}}
Is there any easy solution to make the output like...?
array(2) {
["a"]=>
string(3) "1"
["b"]=>
array(2) {
["c"]=>
string(3) "2"
["d"]=>
array(2) {
[0]=>
array(2) {
["e"]=>
string(9) "3"
["f"]=>
string(4) "4"
}
[1]=>
array(3) {
["e"]=>
string(9) "5"
["f"]=>
string(4) "6"
}}}}
Thanks
You could break each bit into its components and build up the array one step at a time.
$path = "b.d.0.e";
$val = 3;
$output = array();
$parts = explode(".", $path);
// store a pointer to where we currently are in the array.
$curr =& $output;
// loop through up to the second last $part
for ($i = 0, $l = count($parts); $i < $l - 1; ++$i) {
$part = $parts[$i];
// convert numeric strings into integers
if (is_numeric($part)) {
$part = (int) $part;
}
// if we haven't visited here before, make an array
if (!isset($curr[$part])) {
$curr[$part] = array();
}
// jump to the next step
$curr =& $curr[$part];
}
// finally set the value
$curr[$parts[$l - 1]] = $val;
My output, using the same input as yours:
Array (
[a] => 1
[b] => Array (
[c] => 2
[d] => Array (
[0] => Array (
[e] => 3
[f] => 4
)
[1] => Array (
[g] => 5
[h] => 6
)
)
)
)
Or you could use eval():
$raw_data = file($txt_file, FILE_IGNORE_NEW_LINES);
foreach ($raw_data as $line) {
list($keys, $value) = explode('=', $line);
$keys = explode('.', $keys);
$arr_str = '$result';
foreach ($keys as $key) {
if (ctype_digit($key)) {
$arr_str .= "[" . $key . "]";
} else {
$arr_str .= "['" . $key . "']";
}
}
eval($arr_str . ' = $value;');
}
print_r($result);
I know this is an old one, but the best solution I have found is to use array_replace_recursive. It will achieve what you are looking to do:
$start = array(
"600" => array("total" => 100),
"700" => array("total" => 200)
);
$finish = array(
"600" => array("average" => 25),
"700" => array("average" => 50)
);
$out = array_replace_recursive($start,$finish);
var_dump($out):
array(2) {
[600]=>
array(2) {
["total"]=>
int(100)
["average"]=>
int(25)
}
[700]=>
array(2) {
["total"]=>
int(200)
["average"]=>
int(50)
}
}

Categories