Hi I've got a bit of a problem and I can't seem to find the answer. I have an array with arrays in it and want to group these sub arrays into groups based on the same value for a field. This is my code and allows me to sort my arrays based on the arrays inside values. How do I group the result based on shared values? I probably won't know all the values as some are based on date and I want to for instance group all per day/month
if($filter == "ORDER BY TODO_REF DESC"){
$type_sort = 0;
};
if($filter == "ORDER BY TODO_PRIO DESC"){
$type_sort = 2;
};
if($filter == "ORDER BY TODO_DEAD DESC"){
$type_sort = 3;
};
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
aasort($test_array, $type_sort);
print_r($test_array);
Current output:
priority
Array
(
[3] => Array
(
[0] => 2
[1] => sdfsdgdfgdfgdfg
[2] => 3
[3] => 2013-05-30 13:53:23
)
[2] => Array
(
[0] => 1
[1] => This must also be done
[2] => 4
[3] => 2013-03-28 12:13:34
)
[1] => Array
(
[0] => 1
[1] => testing this show me 2
[2] => 5
[3] => 2029-02-23 17:27:20
)
[0] => Array
(
[0] => 1
[1] => Do this task and make sure it gets done
[2] => 5
[3] => 2013-06-28 12:12:41
)
)
What I want would be something like this, where they are split into seperate arrays based on sub array key 2:
Array
(
[3] => Array
(
[0] => 2
[1] => sdfsdgdfgdfgdfg
[2] => 3
[3] => 2013-05-30 13:53:23
)
)
Array
(
[2] => Array
(
[0] => 1
[1] => This must also be done
[2] => 4
[3] => 2013-03-28 12:13:34
)
)
Array
(
[1] => Array
(
[0] => 1
[1] => testing this show me 2
[2] => 5
[3] => 2029-02-23 17:27:20
)
[0] => Array
(
[0] => 1
[1] => Do this task and make sure it gets done
[2] => 5
[3] => 2013-06-28 12:12:41
)
)
$array_1 = array();
$array_2 = array();
foreach($test_array as $item) {
if($item[0] == 1) {
$array_1[] = $item;
} elseif($item[0] == 2) {
$array_2[] = $item;
}
}
$final_array = array($array_1, $array_2);
There must be more optimized codes, but this should serve your needs.
array_multisort() is what you're after it will allow you to sort primary array by sub array and maintain the key value link
I use the below for sorting a rather hefty multi-dimensional array based off sort order arrows asc/desc on a table with many columns and sortable columns. Its abit of a mess but you should be able to follow it.
if (strlen($_GET['col'])<1) {
foreach ($dataarray as $key => $row) {
$spend[$key] = $row[6];
}
array_multisort($spend, SORT_DESC, $dataarray);
} else if ($_GET['col']=="spend"){
foreach ($dataarray as $key => $row) {
$spend[$key] = $row[3];
}
if ($_GET['order']=="asc") {
array_multisort($spend, SORT_ASC, $dataarray);
} else {
array_multisort($spend, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="name"){
foreach ($dataarray as $key => $row) {
$name[$key] = $row[1];
}
if ($_GET['order']=="asc") {
array_multisort($name, SORT_ASC, $dataarray);
} else {
array_multisort($name, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="avg"){
foreach ($dataarray as $key => $row) {
$avg[$key] = $row[4];
}
if ($_GET['order']=="asc") {
array_multisort($avg, SORT_ASC, $dataarray);
} else {
array_multisort($avg, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="sites"){
foreach ($dataarray as $key => $row) {
$sites[$key] = $row[5];
}
if ($_GET['order']=="asc") {
array_multisort($sites, SORT_ASC, $dataarray);
} else {
array_multisort($sites, SORT_DESC, $dataarray);
}
} else if ($_GET['col']=="rate"){
foreach ($dataarray as $key => $row) {
$rate[$key] = $row[6];
}
if ($_GET['order']=="asc") {
array_multisort($rate, SORT_ASC, $dataarray);
} else {
array_multisort($rate, SORT_DESC, $dataarray);
}
} else {
foreach ($dataarray as $key => $row) {
$spend[$key] = $row[2];
}
array_multisort($spend, SORT_DESC, $dataarray);
}
Rather than a block of if-elseif-elseif-elseif...else conditions to determine the sorting/grouping column, I always recommend a lookup array followed by a very quick isset() call. I find this syntax to be more succinct, more readable, and easier to maintain.
So that grouped data is sorted properly, sort the data ahead of time (while it is still in its simpler form). usort() with the spaceship operator (php7) will do all of the hardwork for you. Just be sure to pass the $groupsort variable into the function scope with use.
As you iterate the input array, isolate the identifying column value (and prepare it as necessary), then use it as a temporary key to determine the group in which the $row data should be stored.
Finally, use array_values() to remove the temporary identifying keys (if desired).
Code: (Demo)
$filter = "ORDER BY TODO_PRIO DESC";
$lookup = [
"ORDER BY TODO_REF DESC" => 0,
"ORDER BY TODO_PRIO DESC" => 2,
"ORDER BY TODO_DEAD DESC" => 3
];
$groupsort = isset($lookup[$filter]) ? $lookup[$filter] : 0;
$array = [
[1, "Do this task and make sure it gets done", 5, "2013-06-28 12:12:41"],
[1, "testing this show me 2", 5, "2029-02-23 17:27:20"],
[1, "This must also be done", 4, "2013-03-28 12:13:34"],
[2, "sdfsdgdfgdfgdfg", 3, "2013-05-30 13:53:23"],
[2, "Another priority", 3, "2013-03-28 11:11:11"]
];
// sort DESC on $groupsort column values
usort($array, function($a, $b)use($groupsort) { return $b[$groupsort] <=> $a[$groupsort]; });
// group by $groupsort column values
foreach ($array as $row) {
$id = $row[$groupsort]; // just to improve readability
if ($groupsort == 3) { $id = substr($id, 0, 10); } // remove time from datetime stamp
$result[$id][] = $row; // store the current value
}
var_export(array_values($result)); // reindex first level (remove temp keys);
Output:
array (
0 =>
array (
0 =>
array (
0 => 1,
1 => 'Do this task and make sure it gets done',
2 => 5,
3 => '2013-06-28 12:12:41',
),
1 =>
array (
0 => 1,
1 => 'testing this show me 2',
2 => 5,
3 => '2029-02-23 17:27:20',
),
),
1 =>
array (
0 =>
array (
0 => 1,
1 => 'This must also be done',
2 => 4,
3 => '2013-03-28 12:13:34',
),
),
2 =>
array (
0 =>
array (
0 => 2,
1 => 'sdfsdgdfgdfgdfg',
2 => 3,
3 => '2013-05-30 13:53:23',
),
1 =>
array (
0 => 2,
1 => 'Another priority',
2 => 3,
3 => '2013-03-28 11:11:11',
),
),
)
Related
I have a multidimensional array and am trying to group them according to the value in a specific column.
I'm trying to group them by level, but I won't actually know the level beforehand. So, it's not like I can put it in a for loop and say while $i < 7, because I won't know that 7 is the maximum value for the level key, and frankly, I'm not sure that's how I would need to do it even if I did.
[
['cust' => 'XT8900', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8944', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8922', 'type' => 'premier', 'level' => 3],
['cust' => 'XT8816', 'type' => 'permier', 'level' => 3],
['cust' => 'XT7434', 'type' => 'standard', 'level' => 7],
]
Desired result:
Array (
[1] => Array (
[0] => Array (
[cust] => XT8900
[type] => standard
)
[1] => Array (
[cust] => XT8944
[type] => standard
)
)
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
)
Best way, if you have control over building the initial array, is just set things up like that at the start as you add entries.
If not then build a temporary array to sort:
foreach ($input_arr as $key => &$entry) {
$level_arr[$entry['level']][$key] = $entry;
}
Leaves you with the form you wanted and everything referenced together.
Build the array like that in the first place though if at all possible.
You need to group them by level first
Use foreach to loop into array check if the level is the same with the previous item then group it with that array
$templevel=0;
$newkey=0;
$grouparr[$templevel]="";
foreach ($items as $key => $val) {
if ($templevel==$val['level']){
$grouparr[$templevel][$newkey]=$val;
} else {
$grouparr[$val['level']][$newkey]=$val;
}
$newkey++;
}
print($grouparr);
The output of print($grouparr); will display like the format you hoped for
You can also try to
print($grouparr[7]);
Will display
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
Or
print($grouparr[3]);
Will display
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
Here is the solution I landed on for an identical problem, wrapped as a function:
function arraySort($input,$sortkey){
foreach ($input as $key=>$val) $output[$val[$sortkey]][]=$val;
return $output;
}
To sort $myarray by the key named "level" just do this:
$myArray = arraySort($myArray,'level');
Or if you didn't want it as a function, just for a one time use, this would create $myNewArray from $myArray grouped by the key 'level'
foreach ($myArray as $key=>$val) $myNewArray[$val['level']][]=$val;
function group_assoc($array, $key) {
$return = array();
foreach($array as $v) {
$return[$v[$key]][] = $v;
}
return $return;
}
//Group the requests by their account_id
$account_requests = group_assoc($requests, 'account_id');
$result = array();
foreach ($yourArrayList as $data) {
$id = $data['level'];
if (isset($result[$id])) {
$result[$id][] = $data;
} else {
$result[$id] = array($data);
}
}
Best ans.
$levels = array_unique(array_column($records, 'level'));
$data = array();
foreach($records as $key => $value){
$data[$levels[array_search($value['level'],$levels )]][] = $value ;
}
print_r($data);
To generate the question's exact desured output from the sample input, pull/pop the last value from each row, use that value as the first level grouping key. Then use the original first level index as the second level key. Then push the two remaining elements into the group's subset.
Code: (Demo)
$result = [];
foreach ($array as $key => $row) {
$result[array_pop($row)][$key] = $row;
}
var_export($result);
For functional style syntax, use array_reduce(). (Demo)
var_export(
array_reduce(
array_keys($array),
function($result, $key) use ($array) {
$result[array_pop($array[$key])][$key] = $array[$key];
return $result;
}
)
);
function _group_by($array,$key,$keyName)
{
$return = array();
foreach($array as $val) {
$return[$keyName.$val[$key]][] = $val;
}
return $return;
} //end of function
How to update an array of objects, adding the quantities if you already have the same ID, or if you have not created a new object.
I tried to explain in the code with the arrays and also with the idea of how I would like the result to be.
old Array
$a1 = [
array(
"id" => 1,
"qty" => 1
),
array(
"id" => 2,
"qty" => 1
)
];
$a2 = [
array(
"id" => 1,
"qty" => 1
)
];
$output = array_merge($a1, $a2);
echo '<pre>';
print_r($output);
echo '</pre>';
Result Error:
Array
(
[0] => Array
(
[id] => 1
[qty] => 1
)
[1] => Array
(
[id] => 2
[qty] => 1
)
[2] => Array
(
[id] => 1
[qty] => 1
)
)
What I need, in addition to if the ID does not contain, add.
Array
(
[0] => Array
(
[id] => 1
[qty] => 2
)
[1] => Array
(
[id] => 2
[qty] => 1
)
)
You can take the first array as base, then search for the key (if existing) where the product matches the id. Then either add the quantity and recalculate the price or you just add the reformatted element (id to product conversion).
$result = $a;
foreach($b as $element) {
$matchingProductIndex = array_search($element['id'], array_column($a, 'product'));
if ($matchingProductIndex !== false) {
$pricePerUnit = $result[$matchingProductIndex]['price'] / $result[$matchingProductIndex]['qty'];
$result[$matchingProductIndex]['qty'] += $element['qty'];
$result[$matchingProductIndex]['price'] = $result[$matchingProductIndex]['qty'] * $pricePerUnit;
} else {
$result[] = [
'qty' => $element['qty'],
'product' => $element['id'],
'price' => $element['price'],
];
}
}
print_r($result);
Working example.
Loop through both arrays with foreach and check the ids against each other.
https://paiza.io/projects/lnnl5HeJSFIOz_6KD6HRIw
<?php
$arr1 = [['qty' => 4, 'id' => 4],['qty' => 1,'id' => 30]];
$arr2 = [['id' => 30, 'qty' => 19],['id' => 31, 'qty' => 2]];
$arr3 = [];
foreach($arr1 as $iArr1){
$match = false;
foreach($arr2 as $iArr2){
if($iArr1['id'] === $iArr2['id']){
$arr3[] = ['id' => $iArr1['id'], 'qty' => $iArr1['qty'] + $iArr2['qty']];
$match = true;
}
}
if(!$match){
$arr3[] = $iArr1;
$arr3[] = $iArr2;
}
}
print_r($arr3);
?>
One approach could be one I more often suggested.
First lets merge $a2 with one to simplify looping over one larger collection.
If we then create a small mapping from id to its index in the result array we can update the running total of qty.
$map = [];
$result = [];
// Merge the two and do as per usual, create a mapping
// from id to index and update the qty at the corresponding index.
foreach (array_merge($a1, $a2) as $subarr) {
$id = $subarr['id'];
if (!key_exists($id, $map)) {
$index = array_push($result, $subarr) - 1;
$map[$id] = $index;
continue;
}
$result[$map[$id]]['qty'] += $subarr['qty'];
}
echo '<pre>', print_r($result, true), '</pre>';
Output:
Array
(
[0] => Array
(
[id] => 1
[qty] => 2
)
[1] => Array
(
[id] => 2
[qty] => 1
)
)
I have conditional function which their execution not running as per business meet which to be require transformation as with desired result. This function contain ranking and frequency which are part of multidimensional array and their execution of sum on based of some calculation
I want to add frequency on base of position of ranking which their execution partially run not accurate. could you please help me out.
<?php
$arr = array (
'AMXB 5321' => array(
array("course_title_code" => "AMB 5321",
"content" => "Course",
"total" => "303",
"count" => "85",
"ranking" => array(array(5),array(2,4,5)),
"frequency" => array(array(5),array(1,2,11))),
array("course_title_code" => "AMB 5321",
"content" => "Succeed in the course",
"total" => "300",
"count" => "85",
"ranking" => array(array(3,5),array(3,4,5)),
"frequency" => array(array(1,4),array(1,2,11))
)
));
array_walk($arr, function(&$v,$k){
foreach($v as $key => &$s){
$s['ranking'] = implode(',',range(1,5));
foreach($s['frequency'] as $key => &$value){
$temp = $value;
$value = (count($value) == 5) ? $value : array_merge(array_fill(0, 5 - count($value), 0), $temp);
if($key == 1){
for($i=0;$i<count($value);$i++){
$value[$i] += $s['frequency'][$key-1][$i];
}
$temFormat = implode(',',$s['frequency'][1]);
}
}
unset($s['frequency']);
$s['frequency'] = $temFormat;
}
});
echo "<pre>";
print_r($arr);
?>
Desired Result
Array
(
[AMXB 5321] => Array
(
[0] => Array
(
[course_title_code] => AMB 5321
[content] => Course
[total] => 303
[count] => 85
[ranking] => 1,2,3,4,5
[frequency] => 0,1,0,2,16
)
[1] => Array
(
[course_title_code] => AMB 5321
[content] => Succeed in the course
[total] => 300
[count] => 85
[ranking] => 1,2,3,4,5
[frequency] => 0,0,2,2,15
)
)
)
You can do that like this:
function calRanking($ranks, $freqs) {
$res = array_fill(0, 5, 0); // create array of 0
foreach($ranks as $k => $v) {
foreach(array_map(null, $v, $freqs[$k]) as $e) {
$res[$e[0]-1]+= $e[1]; //add the frequency according to rank key
}
}
return $res;
}
foreach($a as &$v) { // for each calculate and implode
$v["frequency"] = implode(',', calRanking($v["ranking"], $v["frequency"]));
$v["ranking"] = implode(',',range(1,5));
}
I assumed user with a lot of answer and reputation may build the question in more suite-able way for future learning...
Live example: 3v4l
Reference: array-fill, array-map
I am trying to sort an array to ensure that the parent of any item always exists before it in the array. For example:
Array
(
[0] => Array
(
[0] => 207306
[1] => Bob
[2] =>
)
[1] => Array
(
[0] => 199730
[1] => Sam
[2] => 199714
)
[2] => Array
(
[0] => 199728
[1] => Simon
[2] => 207306
)
[3] => Array
(
[0] => 199714
[1] => John
[2] => 207306
)
[4] => Array
(
[0] => 199716
[1] => Tom
[2] => 199718
)
[5] => Array
(
[0] => 199718
[1] => Phillip
[2] => 207306
)
[6] => Array
(
[0] => 199720
[1] => James
[2] => 207306
)
)
In the above array this "fails" as [1][2] (Sam) does not yet exist and nor does [4][2] (Tom).
The correct output would be as, in this case, as both Sam and Tom's parents already exist before they appear in the array:
Array
(
[0] => Array
(
[0] => 207306
[1] => Bob
[2] =>
)
[1] => Array
(
[0] => 199714
[1] => John
[2] => 207306
)
[2] => Array
(
[0] => 199730
[1] => Sam
[2] => 199714
)
[3] => Array
(
[0] => 199728
[1] => Simon
[2] => 207306
)
[4] => Array
(
[0] => 199718
[1] => Phillip
[2] => 207306
)
[5] => Array
(
[0] => 199716
[1] => Tom
[2] => 199718
)
[6] => Array
(
[0] => 199720
[1] => James
[2] => 207306
)
)
I found an answer https://stackoverflow.com/a/12961400/1278201 which was very close but it only seems to go one level deep (i.e. there is only ever one parent) whereas in my case there could be 1 or 10 levels deep in the hierarchy.
How do I sort the array so no value can appear unless its parent already exists before it?
This will trivially order the array (in O(n)) putting first all those with no parent, then these whose parent is already in the array, iteratively, until there's no children having the current element as parent.
# map the children by parent
$parents = ['' => []];
foreach ($array as $val) {
$parents[$val[2]][] = $val;
}
# start with those with no parent
$sorted = $parents[''];
# add the children the current nodes are parent of until the array is empty
foreach ($sorted as &$val) {
if (isset($parents[$val[0]])) {
foreach ($parents[$val[0]] as $next) {
$sorted[] = $next;
}
}
}
This code requires PHP 7, it may not work in some cases under PHP 5. - for PHP 5 compatibility you will have to swap the foreach ($sorted as &$val) with for ($val = reset($sorted); $val; $val = next($sorted)):
# a bit slower loop which works in all versions
for ($val = reset($sorted); $val; $val = next($sorted)) {
if (isset($parents[$val[0]])) {
foreach ($parents[$val[0]] as $next) {
$sorted[] = $next;
}
}
}
Live demo: https://3v4l.org/Uk6Gs
I have two different version for you.
a) Using a "walk the tree" approach with recursion and references to minimize memory consumption
$data = [
[207306,'Bob',''], [199730,'Sam',199714],
[199728,'Simon',207306], [199714,'John',207306],
[199716, 'Tom',199718], [199718,'Phillip',207306],
[199720,'James',207306]
];
$list = [];
generateList($data, '', $list);
var_dump($list);
function generateList($data, $id, &$list) {
foreach($data as $d) {
if($d[2] == $id) {
$list[] = $d; // Child found, add it to list
generateList($data, $d[0], $list); // Now search for childs of this child
}
}
}
b) Using phps built in uusort()function (seems only to work up to php 5.x and not with php7+)
$data = [
[207306,'Bob',''], [199730,'Sam',199714],
[199728,'Simon',207306], [199714,'John',207306],
[199716, 'Tom',199718], [199718,'Phillip',207306],
[199720,'James',207306]
];
usort($data, 'cmp');
var_dump($data);
function cmp($a, $b) {
if($a[2] == '' || $a[0] == $b[2]) return -1; //$a is root element or $b is child of $a
if($b[2] == '' || $b[0] == $a[2]) return 1; //$b is root element or $a is child of $b
return 0; // both elements have no direct relation
}
I checked this works in PHP 5.6 and PHP 7
Sample array:
$array = Array(0 => Array(
0 => 207306,
1 => 'Bob',
2 => '',
),
1 => Array
(
0 => 199730,
1 => 'Sam',
2 => 199714,
),
2 => Array
(
0 => 199728,
1 => 'Simon',
2 => 207306,
),
3 => Array
(
0 => 199714,
1 => 'John',
2 => 207306,
),
4 => Array
(
0 => 199716,
1 => 'Tom',
2 => 199718,
),
5 => Array
(
0 => 199718,
1 => 'Phillip',
2 => 207306,
),
6 => Array
(
0 => 199720,
1 => 'James',
2 => 207306,
),
);
echo "<pre>";
$emp = array();
//form the array with parent and child
foreach ($array as $val) {
$manager = ($val[2] == '') ? 0 : $val[2];
$exist = array_search_key($val[2], $emp);
if ($exist)
$emp[$exist[0]][$val[0]] = $val;
else
//print_R(array_search_key(199714,$emp));
$emp[$manager][$val[0]] = $val;
}
$u_emp = $emp[0];
unset($emp[0]);
//associate the correct child/emp after the manager
foreach ($emp as $k => $val) {
$exist = array_search_key($k, $u_emp);
$pos = array_search($k, array_keys($u_emp));
$u_emp = array_slice($u_emp, 0, $pos+1, true) +
$val +
array_slice($u_emp, $pos-1, count($u_emp) - 1, true);
}
print_R($u_emp); //print the final result
// key search function from the array
function array_search_key($needle_key, $array, $parent = array())
{
foreach ($array AS $key => $value) {
$parent = array();
if ($key == $needle_key)
return $parent;
if (is_array($value)) {
array_push($parent, $key);
if (($result = array_search_key($needle_key, $value, $parent)) !== false)
return $parent;
}
}
return false;
}
Find the below code that might be helpful.So, your output is stored in $sortedarray.
$a=array(array(207306,'Bob',''),
array (199730,'Sam',199714),
array(199728,'Simon',207306),
array(199714,'John',207306),
array(199716,'Tom',199718),
array(199718,'Phillip',207306),
array(199720,'James',207306));
$sortedarray=$a;
foreach($a as $key=>$value){
$checkvalue=$value[2];
$checkkey=$key;
foreach($a as $key2=>$value2){
if($key<$key2){
if ($value2[0]===$checkvalue){
$sortedarray[$key]=$value2;
$sortedarray[$key2]=$value;
}else{
}
}
}
}
print_r($sortedarray);
What about this approach:
Create an empty array result.
Loop over your array and only take the items out of it where [2] is empty and insert them into result.
When this Loop is done you use a foreach-Loop inside a while-loop. With the foreach-Loop you take every item out of your array where [2] is already part of result. And you do this as long as your array contains anything.
$result = array();
$result[''] = 'root';
while(!empty($yourArray)){
foreach($yourArray as $i=>$value){
if(isset($result[$value[2]])){
// use the next line only to show old order
$value['oldIndex'] = $i;
$result[$value[0]] = $value;
unset($yourArray[$i]);
}
}
}
unset($result['']);
PS: You may run into trouble by removing parts of an array while walking over it. If you do so ... try to solve this :)
PPS: Think about a break condition if your array have an unsolved loop or a child without an parent.
you can use your array in variable $arr and use this code it will give you required output.
function check($a, $b) {
return ($a[0] == $b[2]) ? -1 : 1;
}
uasort($arr, 'check');
echo '<pre>';
print_r(array_values($arr));
echo '</pre>';
I have a multidimensional array and am trying to group them according to the value in a specific column.
I'm trying to group them by level, but I won't actually know the level beforehand. So, it's not like I can put it in a for loop and say while $i < 7, because I won't know that 7 is the maximum value for the level key, and frankly, I'm not sure that's how I would need to do it even if I did.
[
['cust' => 'XT8900', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8944', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8922', 'type' => 'premier', 'level' => 3],
['cust' => 'XT8816', 'type' => 'permier', 'level' => 3],
['cust' => 'XT7434', 'type' => 'standard', 'level' => 7],
]
Desired result:
Array (
[1] => Array (
[0] => Array (
[cust] => XT8900
[type] => standard
)
[1] => Array (
[cust] => XT8944
[type] => standard
)
)
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
)
Best way, if you have control over building the initial array, is just set things up like that at the start as you add entries.
If not then build a temporary array to sort:
foreach ($input_arr as $key => &$entry) {
$level_arr[$entry['level']][$key] = $entry;
}
Leaves you with the form you wanted and everything referenced together.
Build the array like that in the first place though if at all possible.
You need to group them by level first
Use foreach to loop into array check if the level is the same with the previous item then group it with that array
$templevel=0;
$newkey=0;
$grouparr[$templevel]="";
foreach ($items as $key => $val) {
if ($templevel==$val['level']){
$grouparr[$templevel][$newkey]=$val;
} else {
$grouparr[$val['level']][$newkey]=$val;
}
$newkey++;
}
print($grouparr);
The output of print($grouparr); will display like the format you hoped for
You can also try to
print($grouparr[7]);
Will display
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
Or
print($grouparr[3]);
Will display
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
Here is the solution I landed on for an identical problem, wrapped as a function:
function arraySort($input,$sortkey){
foreach ($input as $key=>$val) $output[$val[$sortkey]][]=$val;
return $output;
}
To sort $myarray by the key named "level" just do this:
$myArray = arraySort($myArray,'level');
Or if you didn't want it as a function, just for a one time use, this would create $myNewArray from $myArray grouped by the key 'level'
foreach ($myArray as $key=>$val) $myNewArray[$val['level']][]=$val;
function group_assoc($array, $key) {
$return = array();
foreach($array as $v) {
$return[$v[$key]][] = $v;
}
return $return;
}
//Group the requests by their account_id
$account_requests = group_assoc($requests, 'account_id');
$result = array();
foreach ($yourArrayList as $data) {
$id = $data['level'];
if (isset($result[$id])) {
$result[$id][] = $data;
} else {
$result[$id] = array($data);
}
}
Best ans.
$levels = array_unique(array_column($records, 'level'));
$data = array();
foreach($records as $key => $value){
$data[$levels[array_search($value['level'],$levels )]][] = $value ;
}
print_r($data);
To generate the question's exact desured output from the sample input, pull/pop the last value from each row, use that value as the first level grouping key. Then use the original first level index as the second level key. Then push the two remaining elements into the group's subset.
Code: (Demo)
$result = [];
foreach ($array as $key => $row) {
$result[array_pop($row)][$key] = $row;
}
var_export($result);
For functional style syntax, use array_reduce(). (Demo)
var_export(
array_reduce(
array_keys($array),
function($result, $key) use ($array) {
$result[array_pop($array[$key])][$key] = $array[$key];
return $result;
}
)
);
function _group_by($array,$key,$keyName)
{
$return = array();
foreach($array as $val) {
$return[$keyName.$val[$key]][] = $val;
}
return $return;
} //end of function