Transform a 3-dimensional array in PHP - php

I have an array like this :
array(3) {
["FL_1"] => array(3) {
["MIC_1"] => array(1) {
["SP_4"] => float(7)
}
["MIC_13"] => array(1) {
["SP_16"] => float(4)
}
["MIC_6"] => array(1) {
["SP_74"] => float(4)
}
}
["FL_2"] => array(2) {
["MIC_1"] => array(1) {
["SP_5"] => float(4)
}
["MIC_13"] => array(1) {
["SP_17"] => float(4)
}
["MIC_6"] > array(1) {
["SP_75"] => float(4)
}
}
["FL_3"] => array(2) {
["MIC_1"] => array(1) {
["SP_5"] => float(89)
}
["MIC_13"] => array(1) {
["SP_18"] => float(1)
}
["MIC_6"] > array(1) {
["SP_78"] => float(21)
}
}
}
For each FL_X, I need to keep only one MIC_X that follow the conditions below :
1- This MIC_X needs to be the same for each FL_X
2- This MIC_X needs to have the lowest possible SP_Xvalue
From this example I need to get the following array
array(3) {
["FL_1"] => array(1) {
["MIC_13"] => array(1) {
["SP_16"] => float(4)
}
}
["FL_2"] => array(1) {
["MIC_13"] => array(1) {
["SP_17"] => float(6)
}
}
["FL_3"] => array(1) {
["MIC_13"] => array(1) {
["SP_18"] => float(1)
}
}
}
Any help on how to do this would be much appreciated.
Thank you !

Here's one possible solution. It uses array_walk_recursive to find the SP_X key associated with the minimum SP_X value, then it traverses the array to find the MIC_X key associated with that SP_X key and value, and finally it uses array_map and array_filter to extract only those MIC_X key values from the original array:
// find the minimum SP_X value and its key
$min_sp = PHP_INT_MAX;
$min_key = '';
array_walk_recursive($array, function ($v, $k) use (&$min_sp, &$min_key) {
if ($v < $min_sp) {
$min_sp = $v;
$min_key = $k;
}
});
// find the MIC_X key corresponding to the min SP_X value
$mic_key = '';
foreach ($array as $fl) {
foreach ($fl as $mic => $sp) {
if (isset($sp[$min_key]) && $sp[$min_key] == $min_sp) {
$mic_key = $mic;
break 2;
}
}
}
// filter the array to get all the MIC_X values
$out = array_map(function ($fl) use ($mic_key) {
return array_filter($fl, function ($mic) use ($mic_key) {
return $mic == $mic_key;
}, ARRAY_FILTER_USE_KEY);
}, $array);
print_r($out);
Output:
Array
(
[FL_1] => Array
(
[MIC_13] => Array
(
[SP_16] => 4
)
)
[FL_2] => Array
(
[MIC_13] => Array
(
[SP_17] => 4
)
)
[FL_3] => Array
(
[MIC_13] => Array
(
[SP_18] => 1
)
)
)
Demo on 3v4l.org

Related

How to merge subarrays using keys and sum the values?

I'm fairly new to PHP and I'm having some trouble with arrays and combining data. I have the following array which has been created from a foreach loop:
array(1) {
[36868]=> int(3)
}
array(1) {
[2112]=> int(3)
}
array(1) {
[35901]=> int(3)
}
array(1) {
[6496]=> int(3)
}
array(1) {
[87]=> int(3)
}
array(1) {
[36868]=> int(3)
}
array(1) {
[68]=> int(3)
}
array(1) {
[9068]=> int(3)
}
array(1) {
[47]=> int(3)
}
The key in each array is a user ID, so I need to preserve this, but I only want one instance of each key and where there are duplicate keys, sum the values. Like so:
array(1) {
[36868]=> int(6)
}
array(1) {
[2112]=> int(3)
}
array(1) {
[35901]=> int(3)
}
array(1) {
[6496]=> int(3)
}
array(1) {
[87]=> int(3)
}
array(1) {
[68]=> int(3)
}
array(1) {
[9068]=> int(3)
}
array(1) {
[47]=> int(3)
}
The I've tried looping through the array:
foreach ($array as $key => &$value) {
if ($value[0] == $value[1]) {
$value[1] += $value[1];
}
}
But with no luck. I've also tried rendering the arrays differently i.e. [userid]=>1,[score]=>3 and I feel like I'm going round in circles a bit, so any help would be hugely appreciated.
$data <-- this is your original array
$result = array_reduce(
$data,
function($carry, $item) {
foreach ($item as $id => $score) {
if (array_key_exists($id, $carry)) {
$carry[$id] += $score;
} else {
$carry[$id] = $score;
}
}
return $carry;
},
[]
);
If you are sure that each item only contains 1 entry you could also simplify the callback to not use foreach:
$result = array_reduce(
$data,
function ($carry, $item) {
$score = reset($item);
$id = key($item);
if (array_key_exists($id, $carry)) {
$carry[$id] += $score;
} else {
$carry[$id] = $score;
}
return $carry;
},
[]
);
You could also keep using foreach instead:
/** foreach to create a $data array like described below and afterwards do this: **/
$result = [];
foreach($data as $row) {
$score = reset($row);
$id = key($row);
if (array_key_exists($id, $result)) {
$result[$id] += $score;
} else {
$result[$id] = $score;
}
}
This will take an array $data like this:
array(
array('1' => 3),
array('1' => 3),
array('2' => 3),
);
and creates the variable $result like this:
array(
'1' => 6,
'2' => 3,
);
Here is a clean method that will not produce Notices. When merge-summing array data the efficient method is to generate temporary keys and use the very fast isset() function. I could have used current() and key() to access the lone subarray element, but the second foreach control structure is actually faster and more compact. (Ref:
https://stackoverflow.com/a/21219594/2943403 )
Code: (Demo)
$array = [
[36868 => 3],
[2112 => 3],
[35901 => 3],
[6496 => 3],
[87 => 3],
[36868 => 3],
[68 => 3],
[9068 => 3],
[47 => 3]
];
$result = [];
foreach ($array as $subarray) {
foreach ($subarray as $k => $v) {
if (!isset($result[$k])) {
$result[$k] = $subarray;
} else {
$result[$k][$k] += $v;
}
}
}
var_export(array_values($result));
Output:
array (
0 =>
array (
36868 => 6,
),
1 =>
array (
2112 => 3,
),
2 =>
array (
35901 => 3,
),
3 =>
array (
6496 => 3,
),
4 =>
array (
87 => 3,
),
5 =>
array (
68 => 3,
),
6 =>
array (
9068 => 3,
),
7 =>
array (
47 => 3,
),
)

Sort array by the value of the key

i'm trying to sort an array by the value of a sub-key in DESC order but I'm stuck.
I've could make it with ksort but it was in ascending order..
Here's my array :
array_by_lang => array(
[no] => array(
[3-1] => array(//some informations),
[3-10] => array(//informations),
[3-7] => array(//informations),
[5-1] => array(//informations)
)
)
what i want to obtain is something like :
array_by_lang => array(
[no] => array(
[5-1] => array(//informations),
[3-10] => array(//some informations),
[3-7] => array(//informations),
[3-1] => array(//informations)
)
)
Is that possible ? Thanks a lot
I think, you need "reversing natural sort by key". Just with array_multisort and array_reverse (see also natsort):
$array_by_lang = array(
'no' => array(
'3-1' => array('info_1'),
'3-10' => array('info_2'),
'3-7' => array('info_3'),
'5-1' => array('info_4'),
)
);
array_multisort(array_keys($array_by_lang['no']),SORT_NATURAL, $array_by_lang['no']);
$array_by_lang['no'] = array_reverse($array_by_lang['no']); // reverse natural order - "DESC"
var_dump($array_by_lang);
Output
array(1) {
["no"]=>
array(4) {
["5-1"]=>
array(1) {
[0]=>
string(6) "info_4"
}
["3-10"]=>
array(1) {
[0]=>
string(6) "info_2"
}
["3-7"]=>
array(1) {
[0]=>
string(6) "info_3"
}
["3-1"]=>
array(1) {
[0]=>
string(6) "info_1"
}
}
}
This might help -
$a = array(
'3-1' => array('//some informations'),
'3-10' => array('//informations'),
'3-7' => array('//informations'),
'5-1' => array('//informations')
);
## Array for keys
$temp= array();
foreach(array_keys($a) as $v) {
$t = explode('-', $v);
$temp[$t[0]][] = $t[1];
}
## Sort the keys
foreach($temp as &$ar) {
rsort($ar);
}
krsort($temp);
## Final array
$final= array();
foreach($temp as $k => $f) {
foreach($f as $v) {
$key = $k . '-' . $v;
$final[$key] = $a[$key];
}
}
var_dump($final);
Output
array(4) {
["5-1"]=>
array(1) {
[0]=>
string(14) "//informations"
}
["3-10"]=>
array(1) {
[0]=>
string(14) "//informations"
}
["3-7"]=>
array(1) {
[0]=>
string(14) "//informations"
}
["3-1"]=>
array(1) {
[0]=>
string(19) "//some informations"
}
}
DEMO

Search values in php array

I have an array like this:
array(5) {
[0]=> array(1) { ["go-out"]=> string(7) "#0d4b77" }
[1]=> array(1) { ["cycling"]=> string(7) "#1472b7" }
[2]=> array(1) { ["diving"]=> string(7) "#1e73be" }
[3]=> array(1) { ["exploring"]=> string(7) "#062338" }
[4]=> array(1) { ["eating"]=> string(7) "#f79e1b" }
}
Let's say I have the first value like 'cycling', so how can I find the '#147217' value?
I have been trying a lot of combinations of
foreach ( $array as $key => list($key1 ,$val)) {
if ($key1 === $id) {
return $val;
}
}
But no luck.
Ideas?
You can use array_column -
array_column($your_array, 'cycling');
DEMO
You should also add the checks for key's existence.
you may still make one loop
$id = "cycling";
foreach($array as $val)
if(isset($val[$id])) echo $val[$id];
Demo on Evail.in
I have reformated tour code, try this, that works:
$array = array(
0 => array("go-out" => "#0d4b77"),
1 => array("cycling" => "#1472b7"),
2 => array("diving" => "#1e73be"),
3 => array("exploring" => "#062338"),
4 => array("eating" => "#f79e1b")
);
$id = "cycling";
foreach ($array as $key => $entry) {
if ($entry[$id]) {
echo $entry[$id];
}
}
$array = array(
0 => array("go-out" => "#0d4b77"),
1 => array("cycling" => "#1472b7"),
2 => array("diving" => "#1e73be"),
3 => array("exploring" => "#062338"),
4 => array("eating" => "#f79e1b")
);
$search = "cycling";
foreach ($array as $key => $entry)
if (isset($entry[$search]))
echo $entry[$search];
That works.
Nice day.

PHP Reconstruct Array

I need to reconstruct an array. Here is the original array:
array(8) {
[0] => array(1)
{
["L_TRANSACTIONID0"] => string(17) "62M97388AY676841D"
}
[1] => array(1)
{
["L_TRANSACTIONID1"] => string(17) "9FF44950UY3240528"
}
[2] => array(1)
{
["L_STATUS0"] => string(9) "Completed"
}
[3] => array(1)
{
["L_STATUS1"] => string(9) "Completed"
}
}
I would like to reconstruct it to be as such:
array(2) {
[0] => array(2)
{
["L_TRANSACTIONID0"] => string(17) "62M97388AY676841D"
["L_STATUS0"] => string(9) "Completed"
}
[1] => array(1)
{
["L_TRANSACTIONID1"] => string(17) "9FF44950UY3240528"
["L_STATUS1"] => string(9) "Completed"
}
}
Notice that the KEYS both match with the numeric representation... Is this at all possible?
edit:
here is my code I am using:
foreach($comparison as $key => $val) {
$findme1 = 'L_TRANSACTID'.$i++;
$findme2 = 'L_STATUS'.$c++;
$arrDisable = array($findme1,$findme2);
if( in_array($key, $arrDisable ) ) {
unset( $comparison[ $key ][$val]);
}
if( in_array($key, $arrDisable) ) {
unset( $comparison[ $key ][$val]);
}
}
Try this
$labels = array('L_TRANSACTIONID', 'L_STATUS');
$res = array();
foreach($arr as $val) {
$key = str_replace($labels, '', key($val));
$res[$key] = isset($res[$key]) ? array_merge($res[$key], $val) : $val;
}
print_r($res);
http://codepad.org/MwqTPqtA
If you are certain the the vector cointains pairs L_TRANSACTIONIDn / L_STATUSn keys,that is to say, for each transactionID, there is a corresponding status, what you can do, is to get the number of id/status records (which should equal the length of the initial array, divided by two), and compose the resultin keys, by increasing the current element count.
Could look something like this:
$numItems = sizeof($myInitialArray) / 2;
$newArray = array();
for($i = 0; $i < $numItems; $i++)
{
$itemID = $i * 2; // since we're getting id/status pairs, we're using a step equal to 2
$newArray[] = array(
("L_TRANSACTIONID" . $i) => $myInitialArray[$itemID], // this is the id value
("L_STATUS" . $i) => $myInitialArray[$itemID + 1] // this is the status for that id
);
}
Hope this helps. Have a great day!

Filter out keys from multidimensional array

I have the following array:
array(2) {
[0] => array(4) {
["presentation_id"] => int(143)
["user_id"] => int(2)
["session_id"] => int(46)
["submission_id"] => int(190)
}
[1] => array(4) {
["presentation_id"] => int(144)
["user_id"] => int(2)
["session_id"] => int(46)
["submission_id"] => int(190)
}
What I want is to have an array consisting of just certain keys of this array, for example:
array(2) {
[0] => array(4) {
["presentation_id"] => int(143)
["user_id"] => int(2)
}
[1] => array(4) {
["presentation_id"] => int(144)
["user_id"] => int(2)
}
Any ideas?
$array = array_map(function ($arr) {
return array_intersect_key($arr, array_flip(array('presentation_id', 'user_id')));
}, $array);
Important to note that this syntax requires PHP 5.3+.
For other versions:
foreach ($array as &$arr) {
$arr = array_intersect_key($arr, array_flip(array('presentation_id', 'user_id')));
}
I'd suggest this over unsetting unwanted keys (as suggested by others) if you definitely want to restrict the array to certain elements. If you add more elements to the array in the future you won't need to update this code, but you'd have to unset more elements that you may not want.
Try:
$newArray = array_map(function ($innerArray) {
unset($innerArray['session_id'], $innerArray['submission_id'] /*, and so on*/);
return $innerArray;
}, $oldArray);
please use foreach and unset the key which you want to remove. Like
foreach($data as $key=> $row){
unset[$key] ["session_id"] ;
}

Categories