PHP Multidimension array sorting - php

I am trying to sort this multidimensional array based on [sort_order].
I have searched a lot of topics related with no sucess.
Can I have a little help here?
The objective is to sort the array so I can get the array on the following order:
[post_images]
[localizacao]
[post_title]
[category]
Array
(
[[#taxonomy_name#]] => Array
(
[post_title] => Array
(
[name] => post_title
[show_in_email] => 1
[sort_order] => 3
[options] => Array
(
[0] =>
)
)
[post_images] => Array
(
[name] => post_images
[is_active] => 1
[show_on_listing] => 1
[show_on_detail] => 1
[sort_order] => 1
[options] => Array
(
[0] =>
)
)
[category] => Array
(
[name] => category
[is_require] => 1
[is_active] => 1
[show_on_listing] => 1
[show_on_detail] => 1
[show_in_email] => 1
[sort_order] => 4
[options] => Array
(
[0] =>
)
)
[localizacao] => Array
(
[name] => localizacao
[label] => Localização
[htmlvar_name] => localizacao
[sort_order] => 2
[options] => Array
(
[0] =>
)
)
)
)

You may find usort useful, which allows you to sort with a callback function like so:
// The function which will do your comparisons:
function sortOrderCompare ($a, $b) {
$aOrder = $a['sort_order'];
$bOrder = $b['sort_order'];
if ($aOrder == $bOrder) {
// A and B have the same order
return 0;
}else if ($aOrder < $bOrder) {
//A comes before B
return -1;
}else{
// B comes before A
return 1;
}
}
usort($array['[#taxonomy_name#]'], "sortOrderCompare");

You could use array_multisort
Depending on your array structure it looks like this:
foreach( $posts as $post=>$row )
{
$sort_order[$post] = $row['sort_order'];
}
array_multisort( $sort_order, SORT_ASC, $posts );

Related

How To Merge/push array into one in php

code
$result = [];
foreach ($getAllAgent as $rkey => $rvalue) {
$found = -1;
for ($i = 0; $i < count($result); $i++) {
if ($result[$i]["brokerid"] == $rvalue["brokerid"]) {
$found = $i;
$result[$i]['get_agent_details'][] = $rvalue['get_agent_details']; //here to combine
break;
}
}
// if not found, create new
if ($found == -1) {
$result[] = $rvalue;
}
results
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[id] => 3
[name] => kenang
[ic] => 932132923
[phone] => 2313123
[0] => Array
(
[id] => 4
[name] => ivan
[ic] => 32992131
[phone] => 31231
)
)
)
)
I have one set of an array, and I loop it and restructure match the data based on ID. After that I will try to merge the same data into one array, I able add into one array. But it will not combine as one. The correct result should be as below.
[get_agent_details] => Array
(
[0] => Array(
[id] => 3
[name] => kenang
[ic] => 932132923
[phone] => 2313123
),
[1] => Array
(
[id] => 4
[name] => ivan
[ic] => 32992131
[phone] => 31231
)
)
Your problem is in this line:
$result[] = $rvalue;
Consider the case where you only have one item; this will result in:
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[id] => 1
[name] => Chesney Hawkes
[ic] => 932132923
[phone] => 2313123
)
)
)
But to be consistent, you need get_agent_details to be a list of items, that happens to have one entry:
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[0] => Array
(
[id] => 1
[name] => Chesney Hawkes
[ic] => 932132923
[phone] => 2313123
)
)
)
)
So you need to re-arrange your data, for instance by writing:
$rvalue['get_agent_details'] = [0 => $rvalue['get_agent_details']];
$result[] = $rvalue;
Then, since get_agent_details will already be a list when you encounter a second matching item, your existing code in the inner loop will do the right thing:
// Add an item to the list
$result[$i]['get_agent_details'][] = $rvalue['get_agent_details'];

Copying a multi dimensional array of nodes into another array

I am looking to convert a multi dimensional array into another multidimensional array using a recursive function.
Source array :
Array
(
[1] => Array
(
[id] => 1
[source_name] => kk56ca1d0f2378f
[company_id] => 1
[lft] => 1
[rgt] => 18
[parent_id] => 0
[children] => Array
(
[2] => Array
(
[id] => 2
[source_name] => kk56ca1d17f3f63
[company_id] => 1
[lft] => 2
[rgt] => 3
[parent_id] => 1
[children] => Array
(
)
)
[3] => Array
(
[id] => 3
[source_name] => kk56ca1d1ebe975
[company_id] => 1
[lft] => 4
[rgt] => 13
[parent_id] => 1
[children] => Array
(
[6] => Array
(
[id] => 6
[source_name] => kk56ca1fc882ac0
[company_id] => 1
[lft] => 5
[rgt] => 10
[parent_id] => 3
[children] => Array
(
)
)
)
)
)
)
)
which I need to get into the format of
Array
(
[0] => Array
(
[id] => 1
[text] => kk56ca1d0f2378f
[parent_id] => 0
[nodes] => Array
(
[0] => Array
(
[id] => 2
[text] => kk56ca1d17f3f63
[parent_id] => 1
[nodes] => Array
(
)
)
[1] => Array
(
[id] => 3
[text] => kk56ca1d1ebe975
[parent_id] => 1
[nodes] => Array
(
[0] => Array
(
[id] => 6
[text] => kk56ca1fc882ac0
[parent_id] => 3
[nodes] => Array
(
)
)
[1] => Array
(
[id] => 15
[text] => kk
[parent_id] => 3
[nodes] => Array
(
)
)
)
)
)
)
)
I have been trying for hours and getting nowhere with this. Any help would be really appreciated.
The source array has associative indexes (though they are numbers) and the destination array has numerical indexes. Besides this, just need to remove a few indexes and change names of a few.
EDIT :
Specific changes :
change index name source_name to text
change index name children to nodes
unset indexes lft, rgt, company_id
I do not have much experience with recursion so I have trying fruitlessly.
This is what I could come up with :
// pass array of nodes
function convert_array($from){
// this is a node
if(isset($from['source_name']))
{
$temp = array();
$temp['id'] = $from['id'];
convert_array($from['children']);
}
// this is an array of nodes
else
{
foreach($from as $arr)
{
$ret = convert_array($arr);
print_r($ret);
}
}
}
But I am not able to understand what data to be returned and how the new array builds up from the return values.
Here the working function:
function convert_array( $array )
{
$retval = array();
foreach( $array as $row )
{
$child = array();
$child['id'] = $row['id'];
$child['text'] = $row['source_name'];
$child['parent_id'] = $row['parent_id'];
if( count( $row['children'] ) )
{ $child['nodes'] = convert_array( $row['children'] ); }
else
{ $child['nodes'] = array(); }
$retval[] = $child;
}
return $retval;
}
3v4l demo
I think it is self-explanatory, BTW: we init an empty array ($retval), then we perform a foreach loop through all array argument: for each element, we init a new array and we add it id, source_name as text and parent_id; if the children index has elements, we perform a recursive call to fill nodes array index, otherwise we set it to empty array.

PHP Multidimensional sort?

I have a rather annoying array structure to work with and I need to sort it by any arbitrary key combination. 2 records are displayed below but multiple records with or without the same structure will be present when sorting is actioned.
Here are two records.
Array(
[0] => Array
(
[cid] => 1
[title] => Mr
[first_name] => Abet
[last_name] => Simbad
[emails] => Array
(
[374] => Array
(
[eid] => 374
[name] => ski lodge
[email] => simbad#skifree.com
)
[373] => Array
(
[eid] => 373
[name] => work
[email] => simbad#work.com
)
[375] => Array
(
[eid] => 375
[name] => personal
[email] => simbad#gmail.com
)
)
)
[1] => Array
(
[cid] => 2
[title] => Mrs
[first_name] => Angie
[last_name] => Stokes
[emails] => Array
(
[590] => Array
(
[eid] => 590
[name] => work
[email] => angie#gmail.com
)
)
)
So if I wanted to sort by email in ascending order in the emails array, how can I get the second complete record to come first in the result array? angie#gmail.com comes before simbad#....
Also Some records will not contain an emails array. They would be last in the result set.
Any help would be much appreciated.
The array shown is a cut down version but I have addresses, notes, phones and websites in the same annoying structure. Ideally I could sort with something like
$sort = array('emails','email')
$data = sort_data_func('ASC',$sort,$data);
But anything steps in the right direction will help. :)
Here's some code I have so far
$sort = array('emails','email');
foreach($contacts as $ckey => $c){
if(is_array($c[$sort[0]])){
foreach($c[$sort[0]] as $key1 => $sort0){
if($sort0[$sort[1]]!=''){
$res[$sort[0]][$ckey][$sort[1]][] = $sort0[$sort[1]];
}
}
}
}
print_r($res);
Which produces:
Array
(
[emails] => Array
(
[0] => Array
(
[0] => simbad#skifree.com
[1] => simbad#work.com
[2] => simbad#gmail.com
)
[1] => Array
(
[0] => angie#gmail.com
)
)
)
But I have no idea where to go from here.
EDIT
OK I have the records in the currect order now but how can I keep the initial record ID in the resulting array?
Here's what I'm using.
$direction=='ASC'
function cmp_asc($a, $b){
$key = current(array_keys($a));
sort($a[$key]);
$a[$key] = current($a[$key]);
sort($b[$key]);
$b[$key] = current($b[$key]);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
function cmp_desc($a, $b){
$key = current(array_keys($a));
asort($a[$key]);
$a[$key] = current($a[$key]);
asort($b[$key]);
$b[$key] = current($b[$key]);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
if($direction=='ASC'){
usort($res[$sort[0]], 'cmp_asc');
}else{
usort($res[$sort[0]], 'cmp_desc');
}
In
Array
(
[emails] => Array
(
[0] => Array
(
[email] => Array
(
[0] => simbad#skifree.com
[1] => simbad#work.com
[2] => simbad#gmail.com
)
)
[1] => Array
(
[email] => Array
(
[0] => angie#gmail.com
)
)
)
)
Out
Array
(
[emails] => Array
(
[0] => Array
(
[email] => Array
(
[0] => angie#gmnail.com
)
)
[1] => Array
(
[email] => Array
(
[0] => simbad#skifree.com
[1] => simbad#work.com
[2] => simbad#gmail.com
)
)
)
)
One of the usort functions, combined with a self-written comparison function that detects the order in which two elements should be sorted, should do the trick.

How do i merge the arrays in a particular format?

I have following arrays:
1) for total placed
Array
(
[0] => Array
(
[centers] => Array
(
[name] => delhi
[id] => 1
)
[0] => Array
(
[totalplaced] => 8
)
)
[1] => Array
(
[centers] => Array
(
[name] => mumbai
[id] => 2
)
[0] => Array
(
[totalplaced] => 1
)
)
)
2) for total working
Array
(
[0] => Array
(
[centers] => Array
(
[name] => delhi
[id] => 1
)
[0] => Array
(
[totalworking] => 4
)
)
[1] => Array
(
[centers] => Array
(
[name] => mumbai
[id] => 2
)
[0] => Array
(
[totalworking] => 1
)
)
)
3) for total trained
Array
(
[0] => Array
(
[centers] => Array
(
[name] => delhi
[id] => 1
)
[0] => Array
(
[totaltrained] => 8
)
)
[1] => Array
(
[centers] => Array
(
[name] => mumbai
[id] => 2
)
[0] => Array
(
[totaltrained] => 1
)
)
)
I wanted to merge these arrays so that the resultant array should look like this
[newarray] => Array(
[0] => Array (
[centers] => Array
(
[name] => delhi
[id] => 1
[totalplaced] => 8
[totalworking] => 4
[totaltrained] => 8
)
)
[1]=> Array(
[centers] => Array
(
[name] => mumbai
[id] => 2
[totalplaced] => 1
[totalworking] => 1
[totaltrained] => 1
)
)
)
This is the tabular representation of the above data which i want to display
centername totalplaced totalworking totaltrained
delhi 8 4 8
mumbai 1 1 1
Please help me on this.
Thanks
Pankaj Khurana
The difficulty here is that PHP's functions such as array_merge() and array_merge_recursive() will not merge data into numeric keys, but rather will re-key any duplicate numeric key. So for example given two arrays:
array(
'test' => 'abc',
0 => 'xyz'
);
array(
'test' => 'def',
0 => 'uvw'
);
Merging them together with array_merge() will produce an array like:
array(
'test' => 'def',
0 => 'xyz',
1 => 'uvw'
);
So, you need a custom function to be "additive" on any key, regardless of whether it is a string or numeric key. Try this:
function mixed_key_array_merge() {
$args = func_get_args();
$result = array();
foreach ($args as $arg) {
// discard non-array arguments; maybe this could be better handled
if (!is_array($arg)) {
continue;
}
foreach ($arg as $key => $value) {
if (!isset($result[$key])) {
$result[$key] = $value;
} else if (is_array($result[$key])) {
$result[$key] = call_user_func_array('mixed_key_array_merge',array($result[$key],$value));
}
}
}
return $result;
}

PHP Associative array sort

I have an array like one below.
Currently it is sorted alphabetically by the OwnerNickName field.
Now i want to brig the array entry with OwnerNickName 'My House' as the first entry of the array and rest sorted alphabetically by OwnerNickName.
Any idea?
Array
(
[0318B69D-5DEB-11DF-9D7E-0026B9481364] => Array
(
[OwnerNickName] => andy
[Rooms] => Array
(
[0] => Array
(
[Label] => Living Room
[RoomKey] => FC795A73-695E-11DF-9D7E-0026B9481364
)
)
)
[286C29DE-A9BE-102D-9C16-00163EEDFCFC] => Array
(
[OwnerNickName] => anton
[Rooms] => Array
(
[0] => Array
(
[Label] => KidsRoom
[RoomKey] => E79D7991-64DC-11DF-9D7E-0026B9481364
)
[1] => Array
(
[Label] => Basement
[RoomKey] => CC12C0C4-68AA-11DF-9D7E-0026B9481364
)
[2] => Array
(
[Label] => Family Room
[RoomKey] => 67A280D4-64D9-11DF-9D7E-0026B9481364
)
)
)
[8BE18F84-AC22-102D-9C16-00163EEDFCFC] => Array
(
[OwnerNickName] => mike
[Rooms] => Array
(
[0] => Array
(
[Label] => Family Room
[RoomKey] => 1C6AFB39-6835-11DF-9D7E-0026B9481364
)
)
)
[29B455DE-A9BC-102D-9C16-00163EEDFCFC] => Array
(
[OwnerNickName] => My House
[Rooms] => Array
(
[0] => Array
(
[Label] => Basement
[RoomKey] => 61ECFAB2-6376-11DF-9D7E-0026B9481364
)
[1] => Array
(
[Label] => Rec Room
[RoomKey] => 52B8B781-6376-11DF-9D7E-0026B9481364
)
[2] => Array
(
[Label] => Deck
[RoomKey] => FFEB4102-64DE-11DF-9D7E-0026B9481364
)
[3] => Array
(
[Label] => My Room2
[RoomKey] => 112473E4-64DF-11DF-9D7E-0026B9481364
)
[4] => Array
(
[Label] => Bar Room
[RoomKey] => F82C47A8-64DE-11DF-9D7E-0026B9481364
)
)
)
)
You may want to implement your own sorting function, e.g.:
function cmp($a, $b)
{
if ($a['OwnerNickName'] == $b['OwnerNickName']) {
return 0;
}
if ($a['OwnerNickName'] == 'My House') {
return -1;
} else if ($b['OwnerNickName'] == 'My House') {
return 1;
}
return ($a['OwnerNickName'] < $b['OwnerNickName']) ? -1 : 1;
}
usort($array, 'cmp');
If you want to change your mind about which index to sort on or which value should be special, something like this might suit:
function specialSort(array &$array, $index, $specialvalue){
$callback = function($a,$b) use ($index, $specialvalue) { //closure
if ($a[$index] == $b[$index]) return 0;
if ($a[$index] == $specialvalue) return -1;
if ($b[$index] == $specialvalue) return 1;
return ($a[$index] < $b[$index]) ? -1 : 1;
} ;
uasort($array, $callback);
}
$arr=array(
'a'=>array('thing'=>'yay','who'=>'owee'),
'foo'=>array('thing'=>'boo','who'=>'wik'),
'd'=>array('thing'=>'kil','who'=>'ilo'),
'b'=>array('thing'=>'ser','who'=>'uyt'),
'zed'=>array('thing'=>'efv','who'=>'qet')
);
specialSort($arr,'who','ilo');
print_r($arr);
Gives the result:
Array
(
[d] => Array
(
[thing] => kil
[who] => ilo //special value
)
[a] => Array
(
[thing] => yay
[who] => owee
)
[zed] => Array
(
[thing] => efv
[who] => qet
)
[b] => Array
(
[thing] => ser
[who] => uyt
)
[foo] => Array
(
[thing] => boo
[who] => wik
)
)

Categories