Building a recursive function to create a multidimensional array - php

I think what I want is a recursive function, but please let me know if there's another way to achieve what I want to do! I'm not sure I'm going to explain this very well, so please let me know if you need further clarification.
I've got a function, findSeed() which takes an id and returns an array that contains information about the "seed":
function findSeeds($id) {
global $wpdb;
$query = "SELECT * FROM seedTable WHERE id = " . $id;
$seed = $wpdb->get_row($query, ARRAY_A);
return $seed;
}
It returns the following array:
Array
(
[id] => 9
[name] => Sign
[seed1] => 4
[seed2] => 3
)
Where seed 1 and seed 2 are the ids of the seeds needed to create it. I'm looking to make a function that will create a multidimensional array, in the following format, where the first part of the array contains the first "seed", the next contains the two seeds contained in the first, the next contains the two seeds contained in each of those, and so on:
Array
(
[1] => Array
(
[0] => Stripey Wallpaper
)
[2] => Array
(
[0] => Green Block
[1] => Aqua Block
)
[3] => Array
(
[0] => Bricks
[1] => Grass
[2] => Bricks
[3] => Glass Pane
)
[4] => Array
(
[0] => Rock
[1] => Grass
[2] => Dirt
[3] => Rock
[4] => Rock
[5] => Grass
[6] => Rock
[7] => Lava
)
)
I'm doing it so far with a (horrible) function, shown here, but the "map" could be anything between 2 and 8 rows, and I'm struggling to see how to turn it into a neat little function that works for anything:
function makeMap($id) {
// First Row
$rowNum = 1;
$oneSeed = findSeeds($id);
$map[$rowNum][] = $oneSeed[name];
// Second Row
$rowNum = $rowNum + 1;
$twoSeed = findSeeds($oneSeed[seed1]);
$threeSeed = findSeeds($oneSeed[seed2]);
$map[$rowNum][] = $twoSeed[name];
$map[$rowNum][] = $threeSeed[name];
// Third Row
$rowNum = $rowNum + 1;
$fourSeed = findSeeds($twoSeed[seed1]);
$fiveSeed = findSeeds($twoSeed[seed2]);
$sixSeed = findSeeds($threeSeed[seed1]);
$sevenSeed = findSeeds($threeSeed[seed2]);
$map[$rowNum][] = $fourSeed[name];
$map[$rowNum][] = $fiveSeed[name];
$map[$rowNum][] = $sixSeed[name];
$map[$rowNum][] = $sevenSeed[name];
// Fourth Row
$rowNum = $rowNum + 1;
$eightSeed = findSeeds($fourSeed[seed1]);
$nineSeed = findSeeds($fourSeed[seed2]);
$tenSeed = findSeeds($fiveSeed[seed1]);
$elevenSeed = findSeeds($fiveSeed[seed2]);
$twelveSeed = findSeeds($sixSeed[seed1]);
$thirteenSeed = findSeeds($sixSeed[seed2]);
$fourteenSeed = findSeeds($sevenSeed[seed1]);
$fifteenSeed = findSeeds($sevenSeed[seed2]);
$map[$rowNum][] = $eightSeed[name];
$map[$rowNum][] = $nineSeed[name];
$map[$rowNum][] = $tenSeed[name];
$map[$rowNum][] = $elevenSeed[name];
$map[$rowNum][] = $twelveSeed[name];
$map[$rowNum][] = $thirteenSeed[name];
$map[$rowNum][] = $fourteenSeed[name];
$map[$rowNum][] = $fifteenSeed[name];
return $map;
}
It should stop when all the "row" nodes are blank, so the following only needs to return the first two "rows":
Array
(
[1] => Array
(
[0] => Wood Block
)
[2] => Array
(
[0] => Dirt
[1] => Lava
)
[3] => Array
(
[0] =>
[1] =>
[2] =>
[3] =>
)
[4] => Array
(
[0] =>
[1] =>
[2] =>
[3] =>
[4] =>
[5] =>
[6] =>
[7] =>
)
)
Any tips, hints or solutions would be GREATLY appreciated,
Thank you.
Edit: Quick note on why I'd like it in the above format - I'm then printing out the results in a table, with the first seed spanning the entire row, then breaking it down with the children underneath, like so:
$map = makeMap($_POST['theItem']);
$colspan = count(end(array_values($map)));
echo '<h3>' . $map[row1][0] . '</h3><br/>';
echo '<table>';
foreach ($map as $row) {
echo '<tr>';
foreach ( $row as $cell) {
echo '<td colspan="'. $colspan .'"><div class="seed">' . $cell . '</div></td>';
}
$colspan = $colspan / 2;
echo '</tr>';
}
echo '</table>';

<?php
$array = array('one', 'two', 'three');
for($i =1; $i<= count($array); $i++){
for($j=0; $j<$i; $j++){
$arrymulti[$i][$j]= $array[$j];
}
}
echo '<pre>';
print_r($arrymulti);
?>
Output:
Array
(
[1] => Array
(
[0] => one
)
[2] => Array
(
[0] => one
[1] => two
)
[3] => Array
(
[0] => one
[1] => two
[2] => three
)
)
DEMO

You can Use this recursive function That I Wrote It For Class
static public $map;
static function seeder($id,$Depth=0){
$Seed=findSeeds($id);
if(!$Seed){
return self::$map;
}
self::$map[$Depth][]=$Seed['name'];
self::seeder($Seed['seed1'],$Depth+1);
self::seeder($Seed['seed2'],$Depth+1);
if($Depth==0){
foreach(self::$map as $k=>$v){
$Flag=true;
foreach($v as $key=>$Value){
if($Value!="")$Flag=false;
}
if($Flag){
for($i=$k;$i<=count(self::$map);$i++){
#unset(self::$map[$i]);
}
break;
}
}
}
return self::$map;
}
Sample
print_r(seeder($ID));
The output Is similar of Your sample

Related

compare values in array and delete it from array - php

array:
[0] => Array
(
[0] => A
[1] => 70H
[2] => 51.57
[3] => RH
)
[1] => Array
(
[0] => B
[1] => 70H
[2] => 39.11
[3] => RH
)
[2] => Array
(
[0] => C
[1] => 70H
[2] => 12.11
[3] => RH
)
This is just an example of an array, my real array is really big.
I want to find the same values in array like this [key][1], compare their price, find the lowest PRICE [KEY][2]and save [key][0] for all other elements, if the price is the same then random save one as lowest. In the example i give the result that i want will be:
[0] A
[1] B
I tried this code but it doesn't work for me:
$res=array();
$Mfr= arrays_column($final_array, 1);
$dupes = array_diffs(array_count_values($Mfr), array(1)); // how many times a mfr sku appears
print "\nThese are repetitive values:\n[mfrsku] => (number of reps)\n";
foreach($dupes as $key => $val){
$temp = array_intersect_key(arrays_column($final_array, 3), $key);
if(count(array_unique($temp)) < count($temp)){
$temp = array_intersect_key(arrays_column($final_array, 2), array_intersect($Mfr, array($key)));
$temp = array_diffs($temp, array(min($temp)));
$res[] = array_intersect_key(arrays_column($final_array, 0), $temp);
print_r($res);die;
}
}
You can collect during first foreach loop all minimum values and then easily collect records which have another values:
Declaring arrays
$minvals = []; // array of minimum values
$spec = []; // resultant array
$tmp = []; // tmp array (needs for similar records)
First array (collecting minimum values(prices)):
foreach($ar as $rec){
$val = $rec[2]; // price
if(isset($minvals[$rec[1]] )) { // next appearance of the same $rec[1]
if ($minvals[$rec[1]] >= $val) {
$minvals[$rec[1]] = $val;
}
} else { // first appearance
$minvals[$rec[1]] = $val;
}
}
Now you can collect desired values of from the first column:
foreach($ar as $rec){
if ($rec[2] > $minvals[$rec[1]]){ // if price is bigger than minimum
$spec[] = $rec[0];
} else if($rec[2] == $minvals[$rec[1]]){ // if equal
if(isset($tmp[$rec[1]])){ // if it appears at not the first time
$spec[] = $rec[0];
} else {
$tmp[$rec[1]] = 1;
}
}
}
In case of input array like:
$ar = [ ["A","70H","51.57","RH"],
["B","70H","39.11","RH"],
["C","70H","12.11","RH"],
["A2","71H","11.57","RH"],
["B2","71H","32.11","RH"],
["C2","73H","12.11","RH"],
["C3","73H","11.11","RH"],
["C4","73H","33.11","RH"],
["C5","73H","3.11","RH"],
["C6","73H","3.11","RH"],
];
Outputs would be next:
Array
(
[0] => A
[1] => B
[2] => B2
[3] => C2
[4] => C3
[5] => C4
[6] => C6
)
Demo

Filling php array that has missing values

I've a series of arrays with values that goes from 1 to 5. Almost every array has missing values, some even dont have any values. My objective is to fill the missing values with 0. All those arrays are stored into a multidimensional array.
My array looks like:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[2] => Array
(
[0] => 1
[1] => 5
)
[3] => Array
(
[0] => (this array has no values)
)
[4] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
etc...
)
How it should be:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
[4] => 0
)
[2] => Array
(
[0] => 1
[1] => 0
[2] => 0
[3] => 0
[4] => 5
)
[3] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
[4] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
etc...
)
Any help would be appriciated!
For each of your subarrays loop through the numbers 1 to 5, and if that value exists set its key to be one less than its value:
$newarray = array();
foreach($arr as $key => $subarr) {
for ($i = 1; $i <= 5; $i++) {
if (in_array($i, $subarr)) $newarray[$key][$i - 1] = $i;
else $newarray[$key][$i - 1] = 0;
}
}
Where $newarray is your output and $arr is your input array.
You may want to note that PHP does not truly do multidimensional arrays. It only allows you to relate 2 flat arrays together which is not true multidimensionality.
This does not work and will produce results described above.
$menu[1] = "My Training"; //not $menu[1][0]
$menu[1][1] = "To Do List";
$menu[1][2] = "Catalog";
$menu[1][3] = "Self-Report";
$menu[1][4] = "Completions";
$menu[2] = "Manager";
$menu[2][1] = "Direct Reports";
$menu[2][2] = "Incompletes";
$menu[2][3] = "Completions";
$menu[3] = "Instructor";
$menu[3][1] = "My Classes";
$menu[3][2] = "Printables";
$menu[3][3] = "Qualifications";
This does work.
$menu[1] = "My Training"; //not $menu[1][0]
$submenu[1][1] = "To Do List";
$submenu[1][2] = "Catalog";
$submenu[1][3] = "Self-Report";
$submenu[1][4] = "Completions";
$menu[2] = "Manager";
$submenu[2][1] = "Direct Reports";
$submenu[2][2] = "Incompletes";
$submenu[2][3] = "Completions";
$menu[3] = "Instructor";
$submenu[3][1] = "My Classes";
$submenu[3][2] = "Printables";
$submenu[3][3] = "Qualifications";
$submenu is only related to $menu through the first key number as there are no first dimension values to $submenu.
Something like this (array_pad() won't do the trick). $myArray is your source array. Completed array is returned in $result:
$result = array();
foreach( $myArray as $subKey=>$subArray ) {
for( $i=0; $i<5; $i++ ) {
if( isset( $subArray[$i] )) {
$result[$subKey][$i] = $subArray[$i];
} else {
$result[$subKey][$i] = 0;
}
}
}
Note, we do copy of the array. You cannot fill array in-place.
It's been many years since I wrote any PHP but something like this might do the trick I guess?
for($i = 0; $i < 5; $i++)
{
if(empty($myArray[$i])
{
$myArray[$i] = 0;
}
}

Getting parent key in a nested array

I'm building a "nested" array fetching from database; here's my script:
while ($row_rsMaster = mysql_fetch_assoc($rsMaster)) {
$numbers[] = array("Page ");
}
I'd like to obtain the following array (with print_r() function), but I'm totally stuck on how to get the page number:
Array
(
[0] => Array
(
[0] => Page 1
[1] => 1
)
[1] => Array
(
[0] => Page 2
[1] => 2
)
[2] => Array
(
[0] => Page 3
[1] => 3
)
[3] => Array
(
[0] => Page 4
[1] => 4
)
)
I tried:
$numbers[] = array("Pagina " . key($numbers)+1, key($numbers)+1);
but it didn't lead to expected results (in my mind, it should get the current key number of the "parent" array and increment by 1)
Please, any help?
Thanks in advance
Just count by your own:
$n = 0;
while ($row_rsMaster = mysql_fetch_assoc($rsMaster)) {
$n++;
$numbers[] = array("Page ".$n, $n);
}
Or, use count($numbers)+1 in your code:
while ($row_rsMaster = mysql_fetch_assoc($rsMaster)) {
$numbers[] = array("Page ".(count($numbers)+1), count($numbers)+1);
}
Thanks to datacompboy I finally came to this:
while ($row_rsMaster = mysql_fetch_assoc($rsMaster)) {
$counter = count($numbers)+1;
$numbers[] = array("Page " . $counter, $counter);
}

PHP Group array by values

I have an array like this:
Array (
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
[4] => ing_2_ing
[5] => ing_2_amount
[6] => ing_2_det
[7] => ing_2_meas
)
And I want to group the values into an array like this:
Array (
[0] => Array(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[1] => Array(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)
There may be many other items named like that: ing_NUMBER_type
How do I group the first array to the way I want it? I tried this, but for some reason, strpos() sometimes fails:
$i = 1;
foreach ($firstArray as $t) {
if (strpos($t, (string)$i)) {
$secondArray[--$i][] = $t;
} else {
$i++;
}
}
What is wrong? Can you advice?
It depends what you are trying to achieve, if you want to split array by chunks use array_chunk method and if you are trying to create multidimensional array based on number you can use sscanf method in your loop to parse values:
$result = array();
foreach ($firstArray as $value)
{
$n = sscanf($value, 'ing_%d_%s', $id, $string);
if ($n > 1)
{
$result[$id][] = $value;
}
}
<?php
$ary1 = array("ing_1_ing","ing_1_amount","ing_1_det","ing_1_meas","ing_2_ing","ing_2_amount","ing_2_det","ing_2_meas");
foreach($ary1 as $val)
{
$parts = explode("_",$val);
$ary2[$parts[1]][]=$val;
}
?>
This creates:
Array
(
[1] => Array
(
[0] => ing_1_ing
[1] => ing_1_amount
[2] => ing_1_det
[3] => ing_1_meas
)
[2] => Array
(
[0] => ing_2_ing
[1] => ing_2_amount
[2] => ing_2_det
[3] => ing_2_meas
)
)
What I'd do is something like this:
$result = array();
foreach ($firstArray as $value)
{
preg_match('/^ing_(\d+)_/', $value, $matches);
$number = $matches[1];
if (!array_key_exists($number, $result))
$result[$number] = array();
$result[$number][] = $value;
}
Basically you iterate through your first array, see what number is there, and put it in the right location in your final array.
EDIT. If you know you'll always have the numbers start from 1, you can replace $number = $matches[1]; for $number = $matches[1] - 1;, this way you'll get exactly the same result you posted as your example.

php split array between two values

i have an array like:
Array ( [0] => #!A1#DC [1] => #IMSR102.71/74.82 [2] => #HV50 [3] => #PR7/7/ [4] => #RX0 [5] => #ERN/1//0 [6] => #Q2 [7] => #!A1#DC [8] => #IMSR102.50/74.82 [9] => #HV40 [10] => #PR5/5/ [11] => #RX0 [12] => #ERN/1//1 [13] => #Q2 etc etc with hundreds o values
i get this array from a file (with the function file($filename) ) and i need to split it in many subarray.
"!A1#DC" this is the beginning of a series of values ​​that ends with #Q2 but the number of the values between the beginning and the end is not always the same and the only 2 values that are same are the two given ("!A1#DC" for the beginning and "#Q2" for the end)
how can i get somethings like this?
Array (
[0] => Array ( [0] => #!A1#DC [1] => #IMSR102.71/74.82 [2] => #HV50 [3] => #PR7/7/ [4] => #RX0 [5] => #ERN/1//0 [6] => #Q2 )
[1] => Array (
[1] => #!A1#DC [2] => #IMSR102.50/74.82 [3] => #HV40 [4] => #PR5/5/ [5] => #RX0 [6] => #ERN/1//1 [7] => #Q2 etc etc
could you please help me?
thanks
Loop through an array. When you meet starting value, store it's index. When you meet ending value, use array_slice() to extract the part between the last pair of starting and ending values, store this part into another array.
$source = array (
'#!A1#DC',
'#IMSR102.71/74.82',
'#HV50',
'#PR7/7/',
'#RX0',
'#ERN/1//0',
'#Q2',
'#!A1#DC',
'#IMSR102.50/74.82',
'#HV40',
'#PR5/5/',
'#RX0',
'#ERN/1//1',
'#Q2',
);
$dest = array();
$startValue = '#!A1#DC';
$endValue = '#Q2';
$startIndex = 0;
foreach ( $source as $index => $value ) {
if ( $value === $startValue ) {
$startIndex = $index;
} else
if ( $value === $endValue ) {
$dest[] = array_slice($source, $startIndex, $index - $startIndex + 1);
}
}
print_r($dest);
Basically you need to loop through each element of $input, collecting those within START and END elements into a separate array:
$input = array("#!A1#DC", "A", "B", "#Q2");
$values = array();
$current = 0;
define("START", "#!A1#DC");
define("END", "#Q2");
for ($i = 0; $i < count($input); $i++) {
if ($input[$i] == END) {
// Ignore any elements after this point until we see START
$current = null;
} else if ($input[$i] == START) {
// Create a new current collection array
$current = count($values);
$values[$current] = array();
} else {
// Store the value if we are collecting
if ($current !== null) {
$values[$current][] = $input[$i];
}
}
}

Categories