php how to push (accumulating) multidimensional array - php

Please, help with multidimensional array push. Please, see the code and comments below. The push is giving an error. The assigning is giving the last row only.
if (!isset($_SESSION['page_qstn_answer'])) {
$_SESSION['page_qstn_answer'] = array("page" => array(), "qstn" => array(), "answer" => array()
}
if (!isset($temp)) {
$temp = array("page" => array(), "qstn" => array(), "answer" => array() );
}
while($question = mysqli_fetch_assoc($question_set) ) {
if(isset($question['position']) ){
$post_qstn = $question['position'];
If(isset($_POST[$qstn]) ) {
//printing all rows from db correctly as below
//echo "Question ".$qstn." - selected answer ".$answer . " on page ".$page ."<br />";
if (isset($temp) ){
$temp = array ("page"=>$page, "qstn"=>$qstn,"answer"=> $answer);}
//show a one by one array rows correctly but $temp has a one row at a time that is Ok
//print_r($temp);
// Try to accumulate $temp into $_Session array. Push is giving an error
//$_SESSION['pages_qstn_answers'] = array_push($_SESSION['pages_qstn_answers'], $temp);
// No error but no accumulation as foreach as below shows the only one last row.
$_SESSION['pages_qstn_answers'] = $temp;
}
foreach ($_SESSION['pages_qstn_answers'] as $key => $value) {
echo "$key = $value\n";}

I used a function that I found on the website to delete all previously added the same questions before accumulating the $temp entries into the final array as there should be the only one question with a one answer. It seems a working. If somebody could see some shortcomings there please advise. Thanks
remove_elm($_SESSION['pages_qstn_answers'], "qstn", $qstn, TRUE);
$_SESSION['pages_qstn_answers'][] = $temp;
function remove_elm($arr, $key, $val, $within = FALSE) {
foreach ($arr as $i => $array)
if ($within && stripos($array[$key], $val) !== FALSE && (gettype($val) === gettype($array[$key])))
unset($arr[$i]);
elseif ($array[$key] === $val)
unset($arr[$i]);
return array_values($arr);
}

You have a misunderstanding of how array_push() works. It does not return the array, it just appends whatever value you have to it. So when you do:
$_SESSION['pages_qstn_answers'] = array_push($_SESSION['pages_qstn_answers'], $temp);
The right hand side of the equation simply returns an integer containing the number of elements in the new array. So say you now have 5 elements in your array, you are essentially doing
$_SESSION['pages_qstn_answers'] = 5;
Instead just do:
array_push($_SESSION['pages_qstn_answers'], $temp);
or since you're only appending one value I would stick with:
$_SESSION['pages_qstn_answers'][] = $temp;

Related

PHP - Compare array and output found values [duplicate]

I want to separate a PHP array when they have a common prefix.
$data = ['status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6'];
I want each of them in separate variables like $status, $countries, $pms which will contain:
$status = [1,2,3];
$country = [244, 24, 845]
$pms = [4,9,6]
My Current code is taking 1.5 seconds to group them:
$statuses = [];
$countries = [];
$pms = [];
$start = microtime(true);
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
}
}
$time_elapsed_secs = microtime(true) - $start;
print_r($time_elapsed_secs);
I want to know if is there any faster way to do this
This will give you results for more dynamic prefixs - first explode with the delimiter and then insert by the key to result array.
For separating the value you can use: extract
Consider the following code:
$data = array('status.1','status.2','status.3', 'country.244', 'country.24', 'country.845', 'pm.4','pm.9', 'pm.6');
$res = array();
foreach($data as $elem) {
list($key,$val) = explode(".", $elem, 2);
$res[$key][] = $val;
}
extract($res); // this will separate to var with the prefix name
echo "Status is: " . print_r($status); // will output array of ["1","2","3"]
This snippet took less the 0.001 second...
Thanks #mickmackusa for the simplification
Add continue to each of the if's, so if it's one of them, it won't then run the other ones... not really needed in the last one as obviously the loops starts again anyway. Should save a tiny bit of time, but doubt it'll be as much as you probably want to save.
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
continue;
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
continue;
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
continue;
}
}
I'd use explode to split them.
something like this:
$arr = array("status" => [],"country" => [],"pm" => []);
foreach($data as $item){
list($key,$val) = explode(".",$item);
$arr[$key][] = $val;
}
extract($res); // taken from david's answer
and it's a much more readable code (in my opinion)
___ EDIT ____
as #DavidWinder commented, this is both not dynamic and will not result in different variables - look at his answer for the most complete solution for your question
Use Explode. Also is a good way to use $limit param for performance and avoiding wrong behavior on having other '.' in values.
$arr = [];
foreach($data as $item){
list($key,$val) = explode('.', $item, 2);
if (!$key || !$val) continue;
$arr[$key][] = $val;
}
var_dump($arr);
If it was me I would do it like so...
<?php
$data = array ('status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6');
$out = array ();
foreach ( $data AS $value )
{
$value = explode ( '.', $value );
$out[$value[0]][] = $value[1];
}
print_r ( $out );
?>
I'm not sure if this'll boost the performance but you could re-arrange your array in a way that each row has a heading and the corresponding value and then use array_column() to group which data you want.
This is an example of how you could group your data in such a way. (PHP 7.1.25+)
$groupedData = array_map(function($arg) {
[$key, $val] = explode('.', $arg); # for PHP 5.6 < 7.1.25 use list($key, $val) = explode(...)
return array($key => $val);
}, $data);
Then, you can pull out all of the country Id's like so:
$countries = array_column($groupedData, 'country');
Here is a live demo.
You can push data into their respective groups while destructuring. The only iterated function call is explode().
Creating individual variables for each group is a design flaw / mismanagement of array data.
Code: (Demo)
$result = [];
foreach ($data as $value) {
[$prefix, $result[$prefix][]] = explode('.', $value, 2);
}
var_export($result);
Output:
array (
'status' =>
array (
0 => '1',
1 => '2',
2 => '3',
),
'country' =>
array (
0 => '244',
1 => '24',
2 => '845',
),
'pm' =>
array (
0 => '4',
1 => '9',
2 => '6',
),
)
Use sscanf() if you want to directly/explicitly cast the numeric values as integers. Demo

How to separate a php array items by prefix

I want to separate a PHP array when they have a common prefix.
$data = ['status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6'];
I want each of them in separate variables like $status, $countries, $pms which will contain:
$status = [1,2,3];
$country = [244, 24, 845]
$pms = [4,9,6]
My Current code is taking 1.5 seconds to group them:
$statuses = [];
$countries = [];
$pms = [];
$start = microtime(true);
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
}
}
$time_elapsed_secs = microtime(true) - $start;
print_r($time_elapsed_secs);
I want to know if is there any faster way to do this
This will give you results for more dynamic prefixs - first explode with the delimiter and then insert by the key to result array.
For separating the value you can use: extract
Consider the following code:
$data = array('status.1','status.2','status.3', 'country.244', 'country.24', 'country.845', 'pm.4','pm.9', 'pm.6');
$res = array();
foreach($data as $elem) {
list($key,$val) = explode(".", $elem, 2);
$res[$key][] = $val;
}
extract($res); // this will separate to var with the prefix name
echo "Status is: " . print_r($status); // will output array of ["1","2","3"]
This snippet took less the 0.001 second...
Thanks #mickmackusa for the simplification
Add continue to each of the if's, so if it's one of them, it won't then run the other ones... not really needed in the last one as obviously the loops starts again anyway. Should save a tiny bit of time, but doubt it'll be as much as you probably want to save.
foreach($data as $item){
if(strpos($item, 'status.') !== false){
$statuses[]= substr($item,7);
continue;
}
if(strpos($item, 'country.') !== false){
$countries[]= substr($item,8);
continue;
}
if(strpos($item, 'pm.') !== false){
$pms[]= substr($item,3);
continue;
}
}
I'd use explode to split them.
something like this:
$arr = array("status" => [],"country" => [],"pm" => []);
foreach($data as $item){
list($key,$val) = explode(".",$item);
$arr[$key][] = $val;
}
extract($res); // taken from david's answer
and it's a much more readable code (in my opinion)
___ EDIT ____
as #DavidWinder commented, this is both not dynamic and will not result in different variables - look at his answer for the most complete solution for your question
Use Explode. Also is a good way to use $limit param for performance and avoiding wrong behavior on having other '.' in values.
$arr = [];
foreach($data as $item){
list($key,$val) = explode('.', $item, 2);
if (!$key || !$val) continue;
$arr[$key][] = $val;
}
var_dump($arr);
If it was me I would do it like so...
<?php
$data = array ('status.1', 'status.2', 'status.3',
'country.244', 'country.24', 'country.845',
'pm.4', 'pm.9', 'pm.6');
$out = array ();
foreach ( $data AS $value )
{
$value = explode ( '.', $value );
$out[$value[0]][] = $value[1];
}
print_r ( $out );
?>
I'm not sure if this'll boost the performance but you could re-arrange your array in a way that each row has a heading and the corresponding value and then use array_column() to group which data you want.
This is an example of how you could group your data in such a way. (PHP 7.1.25+)
$groupedData = array_map(function($arg) {
[$key, $val] = explode('.', $arg); # for PHP 5.6 < 7.1.25 use list($key, $val) = explode(...)
return array($key => $val);
}, $data);
Then, you can pull out all of the country Id's like so:
$countries = array_column($groupedData, 'country');
Here is a live demo.
You can push data into their respective groups while destructuring. The only iterated function call is explode().
Creating individual variables for each group is a design flaw / mismanagement of array data.
Code: (Demo)
$result = [];
foreach ($data as $value) {
[$prefix, $result[$prefix][]] = explode('.', $value, 2);
}
var_export($result);
Output:
array (
'status' =>
array (
0 => '1',
1 => '2',
2 => '3',
),
'country' =>
array (
0 => '244',
1 => '24',
2 => '845',
),
'pm' =>
array (
0 => '4',
1 => '9',
2 => '6',
),
)
Use sscanf() if you want to directly/explicitly cast the numeric values as integers. Demo

Compare and replace values in array

I need compare 2 arrays , the first array have one order and can´t change , in the other array i have different values , the first array must compare his id with the id of the other array , and if the id it´s the same , take the value and replace for show all in the same order
For Example :
$array_1=array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2=array("4a-walking","2a-cats");
The Result in this case i want get it´s this :
"1a-dogs","2a-cats","3a-birds","4a-walking"
If the id in this case 4a it´s the same , that entry must be modificate and put the value of other array and stay all in the same order
I do this but no get work me :
for($fte=0;$fte<count($array_1);$fte++)
{
$exp_id_tmp=explode("-",$array_1[$fte]);
$cr_temp[]="".$exp_id_tmp[0]."";
}
for($ftt=0;$ftt<count($array_2);$ftt++)
{
$exp_id_targ=explode("-",$array_2[$ftt]);
$cr_target[]="".$exp_id_targ[0]."";
}
/// Here I tried use array_diff and others but no can get the results as i want
How i can do this for get this results ?
Maybe you could use the array_udiff_assoc() function with a callback
Here you go. It's not the cleanest code I've ever written.
Runnable example: http://3v4l.org/kUC3r
<?php
$array_1=array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2=array("4a-walking","2a-cats");
function getKeyStartingWith($array, $startVal){
foreach($array as $key => $val){
if(strpos($val, $startVal) === 0){
return $key;
}
}
return false;
}
function getMergedArray($array_1, $array_2){
$array_3 = array();
foreach($array_1 as $key => $val){
$startVal = substr($val, 0, 2);
$array_2_key = getKeyStartingWith($array_2, $startVal);
if($array_2_key !== false){
$array_3[$key] = $array_2[$array_2_key];
} else {
$array_3[$key] = $val;
}
}
return $array_3;
}
$array_1 = getMergedArray($array_1, $array_2);
print_r($array_1);
First split the 2 arrays into proper key and value pairs (key = 1a and value = dogs). Then try looping through the first array and for each of its keys check to see if it exists in the second array. If it does, replace the value from the second array in the first. And at the end your first array will contain the result you want.
Like so:
$array_1 = array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2 = array("4a-walking","2a-cats");
function splitArray ($arrayInput)
{
$arrayOutput = array();
foreach ($arrayInput as $element) {
$tempArray = explode('-', $element);
$arrayOutput[$tempArray[0]] = $tempArray[1];
}
return $arrayOutput;
}
$arraySplit1 = splitArray($array_1);
$arraySplit2 = splitArray($array_2);
foreach ($arraySplit1 as $key1 => $value1) {
if (array_key_exists($key1, $arraySplit2)) {
$arraySplit1[$key1] = $arraySplit2[$key1];
}
}
print_r($arraySplit1);
See it working here:
http://3v4l.org/2BrVI
$array_1=array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2=array("4a-walking","2a-cats");
function merge_array($arr1, $arr2) {
$arr_tmp1 = array();
foreach($arr1 as $val) {
list($key, $val) = explode('-', $val);
$arr_tmp1[$key] = $val;
}
foreach($arr2 as $val) {
list($key, $val) = explode('-', $val);
if(array_key_exists($key, $arr_tmp1))
$arr_tmp1[$key] = $val;
}
return $arr_tmp1;
}
$result = merge_array($array_1, $array_2);
echo '<pre>';
print_r($result);
echo '</pre>';
This short code works properly, you'll get this result:
Array
(
[1a] => dogs
[2a] => cats
[3a] => birds
[4a] => walking
)

Fetch the value from the key PHP

I have a wordy value array without explisit keys for speed reason. And the keys are populated as numeric keys 0-N automatically:
$array = array('Good old days', 'Bad old days', ....);
The form is filled up with expected key|value pairs:
key=0, value=Good old days
or
<option value="0">Good old days</option>
which is good as I don't want to have long wordy keys.
Now the issue part is, I know how to fetch the key, but I can not find a way how to display the value out of the given key. Maybe because I have to loop for a condition and than the key is grabbed if the condition met.
How do you grab the value from the given key?
Any hint would be very much appreciated.
UPDATE:
//If keys are wordy: http://fonts.googleapis.com/css?family=Quattrocento|Droid+Sans|Yanone+Kaffeesatz
$gwf_settings = array(
'base_font',
'article_title',
'site_name',
'site_slogan',
);
$gwfs = array();
foreach($gwf_settings as $key => $gwf_font) {
//dsm('KEYS: '. $key);
// parent form to check condition if we are using gwf
if (theme_get_setting($gwf_font) == 'gwf') {
$values = $gwfs[theme_get_setting($gwf_font .'_gwf')];
dsm('KEY2: '. theme_get_setting($gwf_font .'_gwf')); //ok, we have the gwf key
dsm('VALUES: '. $values); // BLANK
$gwfs[] = str_replace(' ', '+', $values);
}
}
$google_web_fonts = implode('|', $gwfs);
I seem to get stucked with "values".
UPDATE 2, in case useful to anyone, or any betterment:
$gwf_settings = array(
'base_font',
'article_title',
'site_name',
'site_slogan',
);
$gwf_gwf = array(
'base_font_gwf',
'article_title_gwf',
'site_name_gwf',
'site_slogan_gwf',
);
foreach($gwf_settings as $key => $gwf_font) {
if ( theme_get_setting($gwf_font) == 'gwf' ) {
$gwfs = array();
foreach ($gwf_gwf as $k => $gwf_setting) {
$s = theme_get_setting($gwf_setting);
$fonts = get_gwf();
if ( $s ) {
foreach ($fonts as $f => $val) {
if ( $f == $s ) {
$gwfs[] = str_replace(' ', '+', $val);
}
}
}
}
}
}
$google_web_fonts = implode('|', $gwfs);
// The final output will be just like with wordy key version:
//http://fonts.googleapis.com/css?family=Oswald|Yanone+Kaffeesatz|Droid+Sans
echo $array[0] will print 'Good old days'.
If you have the key, you can use it the same as always:
$array[$key]

php array keys problem

I have the following code:
$rt1 = array
(
'some_value1' => 'xyz1',
'some_value2' => 'xyz2',
'value_1#30'=>array('0'=>1),
'value_2#30'=>array('0'=>2),
'value_3#30'=>array('0'=>3),
'value_1#31'=>array('0'=>4),
'value_2#31'=>array('0'=>5),
'value_3#31'=>array('0'=>6),
'some_value3' => 'xyz3',
'some_value4' => 'xyz4',
);
$array_30 = array
(
'0'=>1,
1=>'2',
2=>'3'
);
$array_31 = array
(
'0'=>4,
'1'=>'5',
'2'=>'6'
);
I need to make it an array and insert the array_30 and array_31 into a DB.
foreach($rt1 as $value){
$rt2[] = $value['0'];
}
The question was updated, so here is an updated answer. Quick check, you should really try and update this to whatever more generic purpose you have, but as a proof of concept, a runnable example:
<?php
$rt1 = array
(
'some_value1' => 'xyz1',
'some_value2' => 'xyz2',
'value_1#30'=>array('0'=>1),
'value_2#30'=>array('0'=>2),
'value_3#30'=>array('0'=>3),
'value_1#31'=>array('0'=>4),
'value_2#31'=>array('0'=>5),
'value_3#31'=>array('0'=>6),
'some_value3' => 'xyz3',
'some_value4' => 'xyz4',
);
$finalArrays = array();
foreach($rt1 as $key=>$value){
if(is_array($value)){
$array_name = "array_".substr($key,-2);
${$array_name}[] = $value['0'];
}
}
var_dump($array_30);
var_dump($array_31);
?>
will output the two arrays with the numbers 1,2,3 and 4,5,6 respectivily
i assume you want to join the values of each of the second-level arrays, in which case:
$result = array();
foreach ($rt1 as $arr) {
foreach ($arr as $item) {
$result[] = $item;
}
}
Inspired by Nanne (which reminded me of dynamically naming variables), this solution will work with every identifier after the \#, regardless of its length:
foreach ( $rt1 as $key => $value )
{
if ( false == strpos($key, '#') ) // skip keys without #
{
continue;
}
// the part after the # is our identity
list(,$identity) = explode('#', $key);
${'array_'.$identity}[] = $rt1[$key]['0'];
}
Presuming that this is your actual code, probably you will need to copy the array somewhere using foreach and afterwards create the new array as you wish:
foreach($arr as $key => $value) {
$arr[$key] = 1;
}

Categories