Sorting multi-dimensional array by count of subarray - php

I have the array like this:
Array
(
[28748] => stdClass Object
(
[uid] => 28748
[status] => 1
[children] => Array
(
[29163] => stdClass Object
(
[uid] => 29163
[status] => 1
)
)
)
[28708] => stdClass Object
(
[uid] => 28708
[status] => 1
[children] => Array
(
[27104] => stdClass Object
(
[uid] => 27104
[status] => 1
[children] => Array
(
[28250] => stdClass Object
(
[uid] => 28250
[status] => 1
)
)
)
[29448] => stdClass Object
(
[uid] => 29448
[status] => 1
[children] => Array
(
[28528] => stdClass Object
(
[uid] => 28528
[status] => 1
)
[28329] => stdClass Object
(
[uid] => 28329
[status] => 1
[children] => Array
(
[28533] => stdClass Object
(
[uid] => 28533
[status] => 1
)
)
[26548] => stdClass Object
(
[uid] => 26548
[status] => 1
)
)
)
)
)
)
And I want to sort the array by the count of sub array, so the no of children is greater will come first. The level of dimension is unlimited. In my case I want to become this array:
Array
(
[28708] => stdClass Object
(
[uid] => 28708
[status] => 1
[children] => Array
(
[29448] => stdClass Object
(
[uid] => 29448
[status] => 1
[children] => Array
(
[28329] => stdClass Object
(
[uid] => 28329
[status] => 1
[children] => Array
(
[28533] => stdClass Object
(
[uid] => 28533
[status] => 1
)
)
[28528] => stdClass Object
(
[uid] => 28528
[status] => 1
)
[26548] => stdClass Object
(
[uid] => 26548
[status] => 1
)
)
)
[27104] => stdClass Object
(
[uid] => 27104
[status] => 1
[children] => Array
(
[28250] => stdClass Object
(
[uid] => 28250
[status] => 1
)
)
)
)
)
[28748] => stdClass Object
(
[uid] => 28748
[status] => 1
[children] => Array
(
[29163] => stdClass Object
(
[uid] => 29163
[status] => 1
)
)
)
)
Here is the new array that i am checking:
Array
(
[27104] => stdClass Object
(
[uid] => 27104
[status] => 1
[children] => Array
(
[28250] => stdClass Object
(
[uid] => 28250
[status] => 1
[children] => Array
(
[28839] => stdClass Object
(
[uid] => 28839
[status] => 1
[children] => Array
(
[27102] => stdClass Object
(
[uid] => 27102
[status] => 1
)
)
)
)
)
[26551] => stdClass Object
(
[uid] => 26551
[status] => 1
[children] => Array
(
[25368] => stdClass Object
(
[uid] => 25368
[status] => 1
)
)
)
)
)
[28708] => stdClass Object
(
[uid] => 28708
[status] => 1
[children] => Array
(
[29448] => stdClass Object
(
[uid] => 29448
[status] => 1
[children] => Array
(
[28528] => stdClass Object
(
[uid] => 28528
[status] => 1
)
[28329] => stdClass Object
(
[uid] => 28329
[status] => 1
[children] => Array
(
[28654] => stdClass Object
(
[uid] => 28654
[status] => 1
)
)
)
[26548] => stdClass Object
(
[uid] => 26548
[status] => 1
)
)
)
)
)
[28748] => stdClass Object
(
[uid] => 28748
[status] => 1
[children] => Array
(
[28838] => stdClass Object
(
[uid] => 28838
[status] => 1
)
[28685] => stdClass Object
(
[uid] => 28685
[status] => 1
)
[29163] => stdClass Object
(
[uid] => 29163
[status] => 1
)
)
)
)
and after using "sortByNumChildren($data)" i'm getting
Array
(
[28748] => stdClass Object
(
[uid] => 28748
[status] => 1
[children] => Array
(
[29163] => stdClass Object
(
[uid] => 29163
[status] => 1
)
[28685] => stdClass Object
(
[uid] => 28685
[status] => 1
)
[28838] => stdClass Object
(
[uid] => 28838
[status] => 1
)
)
)
[28708] => stdClass Object
(
[uid] => 28708
[status] => 1
[children] => Array
(
[29448] => stdClass Object
(
[uid] => 29448
[status] => 1
[children] => Array
(
[26548] => stdClass Object
(
[uid] => 26548
[status] => 1
)
[28329] => stdClass Object
(
[uid] => 28329
[status] => 1
[children] => Array
(
[28654] => stdClass Object
(
[uid] => 28654
[status] => 1
)
)
)
[28528] => stdClass Object
(
[uid] => 28528
[status] => 1
)
)
)
)
)
[27104] => stdClass Object
(
[uid] => 27104
[status] => 1
[children] => Array
(
[26551] => stdClass Object
(
[uid] => 26551
[status] => 1
[children] => Array
(
[25368] => stdClass Object
(
[uid] => 25368
[status] => 1
)
)
)
[28250] => stdClass Object
(
[uid] => 28250
[status] => 1
[children] => Array
(
[28839] => stdClass Object
(
[uid] => 28839
[status] => 1
[children] => Array
(
[27102] => stdClass Object
(
[uid] => 27102
[status] => 1
)
)
)
)
)
)
)
)
and this looks incorrect as this is not sorted by all children's count.
sorting should be according to the number of all descendants.
Please check this.

thank you so much for your answer #trincot .
but i think one thing i missed here
if the total number of children is greater then that array will come first.
As mentioned in my array suppose i have added 2 more elements in the first sub array likewise
28748 => stdClass Object
(
[uid] => 28748
[status] => 1
[children] => Array
(
[29163] => stdClass Object
(
[uid] => 29163
[status] => 1
)
[29173] => stdClass Object
(
[uid] => 29173
[status] => 1
)
[29174] => stdClass Object
(
[uid] => 29174
[status] => 1
)
)
)
total no of children in first sub array = 3
total no of children in second sub array = 7
but total no of children(counting inner children as well) in the second sub array is greater so the second sub array will come first and this shold work same as in the inner part as well.
Please look into this.

You could use a recursive function that sorts each level with uasort:
function sortByNumChildren(&$array) {
foreach ($array as $key => &$obj) {
if (isset($obj->children)) sortByNumChildren($obj->children);
}
uasort($array, function ($a, $b) {
if (!isset($a->children)) return 1;
if (!isset($b->children)) return -1;
return count($b->children) - count($a->children);
});
}
Call this function as follows:
sortByNumChildren($data);
See it run, together with output, on eval.in
This code will sort by number of (immediate) children. See below for sorting on number of descendants.
Code for sorting by number of all descendants
As requested here is an alternative piece of code which sorts the nested array by number of descendants, so also counting grandchildren and their children, etc.:
function sortByNumChildren(&$array) {
$childCounts = array();
foreach ($array as &$obj) {
$childCounts[$obj->uid] = isset($obj->children) ?
sortByNumChildren($obj->children) : 0;
}
uasort($array, function ($a, $b) use ($childCounts) {
return $childCounts[$b->uid] - $childCounts[$a->uid];
});
return count($array) + array_sum($childCounts);
}
Call this function as follows:
sortByNumChildren($data);
See it run, together with output, on eval.in

Related

yet another PHP recursive function for a recursive object array

I select all the category elements starting from parent id= 0 and put the items which their parent id value equals to parent node's id.
public function get_categories($table_name, $parent_id = 0)
{
$this->db->where('`parent`', $parent);
$parent = $this->db->get($table_name);
$categories = $parent->result();
$i = 0;
foreach ($categories as $p_cat) {
$categories[$i]->sub = $this->sub_categories($table_name, $p_cat->id);
$i++;
}
return $categories;
}
public function sub_categories($table_name, $id)
{
$this->db->where('`parent`', $id);
$child = $this->db->get($table_name);
$categories = $child->result();
$i = 0;
foreach ($categories as $p_cat) {
$categories[$i]->sub = $this->sub_categories($table_name, $p_cat->id);
$i++;
}
return $categories;
}
This is the output of my_categories table. $categories content is as follows:
Array (
[0] => stdClass Object (
[id] => 1
[name] => XMLELEMENT10
[parent] => 0
[sub] => Array (
[0] => stdClass Object (
[id] => 13
[name] => XMLELEMENT113
[parent] => 1
[sub] => Array ( )
)
[1] => stdClass Object (
[id] => 14
[name] => XMLELEMENT114
[parent] => 1
[sub] => Array ( )
)
[2] => stdClass Object (
[id] => 15
[name] => XMLELEMENT115
[parent] => 1
[sub] => Array ( ) )
[3] => stdClass Object (
[id] => 16
[name] => XMLELEMENT116
[parent] => 1
[sub] => Array ( )
)
)
)
[1] => stdClass Object (
[id] => 2
[name] => XMLELEMENT20
[parent] => 0
[sub] => Array (
[0] => stdClass Object (
[id] => 5
[name] => XMLELEMENT52
[parent] => 2
[sub] => Array ( )
)
)
)
[2] => stdClass Object (
[id] => 3
[name] => XMLELEMENT30
[parent] => 0
[sub] => Array (
[0] => stdClass Object (
[id] => 6
[name] => XMLELEMENT63
[parent] => 3
[sub] => Array ( )
)
[1] => stdClass Object (
[id] => 7
[name] => XMLELEMENT73
[parent] => 3
[sub] => Array ( )
)
[2] => stdClass Object (
[id] => 8
[name] => XMLELEMENT83
[parent] => 3
[sub] => Array ( )
)
[3] => stdClass Object (
[id] => 9
[name] => XMLELEMENT93
[parent] => 3
[sub] => Array ( )
)
)
)
[3] => stdClass Object (
[id] => 4
[name] => XMLELEMENT40
[parent] => 0
[sub] => Array (
[0] => stdClass Object (
[id] => 10
[name] => XMLELEMENT104
[parent] => 4
[sub] => Array ( )
)
[1] => stdClass Object (
[id] => 11
[name] => XMLELEMENT2017114
[parent] => 4
[sub] => Array ( )
)
[2] => stdClass Object (
[id] => 12
[name] => XMLELEMENT122
[parent] => 4
[sub] => Array ( )
)
)
)
[4] => stdClass Object (
[id] => 17
[name] => XMLELEMENT170
[parent] => 0
[sub] => Array (
[0] => stdClass Object (
[id] => 18
[name] => XMLELEMENT1817
[parent] => 17
[sub] => Array ( )
)
[1] => stdClass Object (
[id] => 19
[name] => XMLELEMENT1917
[parent] => 17
[sub] => Array ( )
)
[2] => stdClass Object (
[id] => 20
[name] => XMLELEMENT2017
[parent] => 17
[sub] => Array ( )
)
)
)
)
Question is simple but I cannot figure out. I just need to list all items like
<ul>
<li>root
<!-- if has children -->
<ul>
<li>child
<!-- if has children -->
<ul>
<li>child of child
.
.
.
</ul>
</li>
</ul>
I was unable to write that simple recursive function.
Very simple solution:
<?php
function printList(array $data){
print "<ul>\n";
foreach($data as $set){
print "<li>$set->name";
if(is_array($set->sub) && count($set->sub)){
print "\n";
printList($set->sub);
}
print "</li>\n";
}
print "</ul>\n";
}
#example data like your $categories array
$subexample = new stdClass;
$subexample->name = 'foobar';
$subexample->sub = array();
$example = new stdClass;
$example->name = 'foobar';
$example->sub = array($subexample);
$data = array($example,$example,$example);
printList($data);

PHP parse soapClient response transfer to a table

I'm just on the hose and dont get on.
I am not a professional programmer but have so far with much reading and over numerous attempts everything so far created what I have undertaken, only with this I have probably found my masterpiece.
I have a response of a SOAP query and would like to display the values in a table for each powerUnitidentifier. What is the best way to do this?
(
[RawData] => stdClass Object
(
[from] => 2022-05-10T01:00:00+02:00
[to] => 2022-05-10T01:20:00+02:00
[dataRecords] => stdClass Object
(
[record] => Array
(
[0] => stdClass Object
(
[powerUnitIdentifier] => abc123
[time] => 2022-05-10T01:00:00+02:00
[fields] => stdClass Object
(
[field] => Array
(
[0] => stdClass Object
(
[identifier] => 100
[value] => 0
)
[1] => stdClass Object
(
[identifier] => 101
[value] => 3.27
)
[2] => stdClass Object
(
[identifier] => 102
[value] => 70.00
)
)
)
)
[1] => stdClass Object
(
[powerUnitIdentifier] => zyx321
[time] => 2022-05-10T01:00:00+02:00
[fields] => stdClass Object
(
[field] => Array
(
[0] => stdClass Object
(
[identifier] => 100
[value] => 0
)
[1] => stdClass Object
(
[identifier] => 101
[value] => 3.19
)
[2] => stdClass Object
(
[identifier] => 102
[value] => 70.00
)
)
)
)
[2] => stdClass Object
(
[powerUnitIdentifier] => abc123
[time] => 2022-05-10T01:10:00+02:00
[fields] => stdClass Object
(
[field] => Array
(
[0] => stdClass Object
(
[identifier] => 100
[value] => 0
)
[1] => stdClass Object
(
[identifier] => 101
[value] => 3.15
)
[2] => stdClass Object
(
[identifier] => 102
[value] => 70.00
)
)
)
)
[3] => stdClass Object
(
[powerUnitIdentifier] => zyx321
[time] => 2022-05-10T01:10:00+02:00
[fields] => stdClass Object
(
[field] => Array
(
[0] => stdClass Object
(
[identifier] => 100
[value] => 0
)
[1] => stdClass Object
(
[identifier] => 101
[value] => 3.09
)
[2] => stdClass Object
(
[identifier] => 102
[value] => 70.00
)
)
)
)
)
)
)
)```
You loop over the section of the data, starting the foreach loop at the right level of your data structure
foreach($theName->RawData->DataRecords->record as $obj) {
echo $obj->powerUnitIdentifier;
}
Or if you ment to process the sub array of that
foreach($theName->RawData->DataRecords->record as $obj) {
echo $obj->powerUnitIdentifier . '<br>';
foreach( $obj->fields as $field) {
echo $field->identifier . ',' . $field->value . '<br>';
}
}

usort not working for laravel multidimensional arrays

I have an array
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => stdClass Object
(
[id] => 79
[name] => shelin
[status] => 0
)
[1] => stdClass Object
(
[id] => 80
[name] => shanu
[status] => 2
)
[2] => stdClass Object
(
[id] => 81
[name] => linto
[status] => 2
)
[3] => stdClass Object
(
[id] => 82
[name] => joseph
[status] => 0
)
)
)
I want to rearrange this array by status desc order
I try
usort($usersdetailsA, function($a, $b) {
return $a->status <=> $b->status;
});
I got an error like
usort() expects parameter 1 to be array, object given
I tried
$usersdetailsA = $this->$usersdetailsA->getValues();
the i got an error like
Undefined property:
TCG\Voyager\Http\Controllers\Users::$[{"id":79,"name":"shelin","status":0},{"id":80,"name":"shanu","status":"2"},{"id":81,"name":"linto","status":"2"},{"id":82,"name":"joseph","status":0}]
Expected output
Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => stdClass Object
(
[id] => 80
[name] => shanu
[status] => 2
)
[1] => stdClass Object
(
[id] => 81
[name] => linto
[status] => 2
)
[2] => stdClass Object
(
[id] => 79
[name] => shelin
[status] => 0
)
[3] => stdClass Object
(
[id] => 82
[name] => joseph
[status] => 0
)
Any help would be appreciated.Thanks in advance
You can sort a collection with sort methods by a given key:
$sorted = $collection->sortByDesc('status');

How to Print response in csv file using PHP

I have response array in variable $listing array .Here is $listing Value:
Array
(
[0] =>
[1] => stdClass Object
(
[status] => failure
[response] => Array
(
[0] => stdClass Object
(
[ProId] => 1
[status] => failure
[errors] => Array
(
[0] => stdClass Object
(
[errorCode] => CONTENT_NOT_FOUND
[message] => Content not found.
[attributeName] =>
)
)
)
[1] => stdClass Object
(
[ProId] => 2
[status] => failure
[errors] => Array
(
[0] => stdClass Object
(
[errorCode] => CONTENT_NOT_FOUND
[message] => Content not found.
[attributeName] =>
)
)
)
[2] => stdClass Object
(
[ProId] => 3
[status] => updated
[errors] => Array
(
)
)
[3] => stdClass Object
(
[ProId] => 4
[status] => updated
[errors] => Array
(
)
)
[4] => stdClass Object
(
[ProId] => 5
[status] => updated
[errors] => Array
(
)
)
[5] => stdClass Object
(
[ProId] => 6
[status] => updated
[errors] => Array
(
)
)
[6] => stdClass Object
(
[ProId] => 7
[status] => updated
[errors] => Array
(
)
)
[7] => stdClass Object
(
[ProId] => 8
[status] => updated
[errors] => Array
(
)
)
[8] => stdClass Object
(
[ProId] => 9
[status] => updated
[errors] => Array
(
)
)
[9] => stdClass Object
(
[ProId] => 10
[status] => updated
[errors] => Array
(
)
)
)
)
[2] => stdClass Object
(
[status] => failure
[response] => Array
(
[0] => stdClass Object
(
[ProId] => 11
[status] => failure
[errors] => Array
(
[0] => stdClass Object
(
[errorCode] => CONTENT_NOT_FOUND
[message] => Content not found.
[attributeName] =>
)
)
)
[1] => stdClass Object
(
[ProId] => 12
[status] => failure
[errors] => Array
(
[0] => stdClass Object
(
[errorCode] => CONTENT_NOT_FOUND
[message] => Content not found.
[attributeName] =>
)
)
)
[2] => stdClass Object
(
[ProId] => 13
[status] => failure
[errors] => Array
(
[0] => stdClass Object
(
[errorCode] => CONTENT_NOT_FOUND
[message] => Content not found.
[attributeName] =>
)
)
)
[3] => stdClass Object
(
[ProId] => 14
[status] => updated
[errors] => Array
(
)
)
[4] => stdClass Object
(
[ProId] => 15
[status] => updated
[errors] => Array
(
)
)
[5] => stdClass Object
(
[ProId] => 16
[status] => updated
[errors] => Array
(
)
)
[6] => stdClass Object
(
[ProId] => 17
[status] => updated
[errors] => Array
(
)
)
[7] => stdClass Object
(
[ProId] => 18
[status] => updated
[errors] => Array
(
)
)
[8] => stdClass Object
(
[ProId] => 19
[status] => updated
[errors] => Array
(
)
)
[9] => stdClass Object
(
[ProId] => 20
[status] => updated
[errors] => Array
(
)
)
)
)
)
I want to create one csv file with above response in below format .Please see attached image
For achieving this result i am using this code:
$fp = fopen('output.csv',"w");
$rowcounts=0;
$resultResponse=$listing->response;
while($rowcounts<$inputfielscount) {
$result=$resultResponse[$rowcounts];
$resultProId=$result->ProId;
$resultStatus=$result->status;
$resultErrors=$result->errors;
$errorMsgArray=$resultErrors[0];
$ErrorsMessage=$errorMsgArray->message;
$ErrorCode=$errorMsgArray->errorCode;
if($resultStatus=='failure'){
$list = array ($resultProId,$resultStatus,$ErrorCode,$ErrorsMessage);
}else {
$list = array ($resultProId,$resultStatus,"successfully");
}
fputcsv($fp,$list);
$rowcounts++;
}
$listing is an response array what i already mansioned at first.
I am not getting the desired result in csv file.If anyone has solution please share.
This I think will shove it into an flat multi-diamential array, not too much trouble to then get it into a csv.
foreach($array as $key => $value) {
if(isset($array[$key]) && count($array[$key]) > 0) {
foreach($array[$key] as $inner) {
$error = $inner['errors'][0];
$new_array[] = array($inner->ProId,$inner->status,$error->errorCode,$error->message);
}
}
}

Having problems with recursive array objects (stdClass Object)

I'm hoping someone can help me with my syntax. I think that's the issue. I'm trying to have the loop go through display the chosen object, but it's not working. Here is my code.
stdClass Object
(
[result_count] => 2
[total_count] => 2
[next_offset] => 2
[entry_list] => Array
(
[0] => stdClass Object
(
[id] => da2b0ab5-873b-d9a8-0fcd-5180871e57eb
[module_name] => Project
[name_value_list] => stdClass Object
(
[description] => stdClass Object
(
[name] => description
[value] => soccer is fun!!!
)
[priority] => stdClass Object
(
[name] => priority
[value] => Primary
)
[total_years_played_c] => stdClass Object
(
[name] => total_years_played_c
[value] => 5
)
[sport_c] => stdClass Object
(
[name] => sport_c
[value] => Soccer
)
[high_school_exp_c] => stdClass Object
(
[name] => high_school_exp_c
[value] => 2
)
[varsity_exp_c] => stdClass Object
(
[name] => varsity_exp_c
[value] => default
)
[hand_right_c] => stdClass Object
(
[name] => hand_right_c
[value] => 0
)
[hand_left_c] => stdClass Object
(
[name] => hand_left_c
[value] => 1
)
[foot_right_c] => stdClass Object
(
[name] => foot_right_c
[value] => 1
)
[foot_left_c] => stdClass Object
(
[name] => foot_left_c
[value] => 0
)
[specialskills_c] => stdClass Object
(
[name] => specialskills_c
[value] =>
)
[varsity_starter_c] => stdClass Object
(
[name] => varsity_starter_c
[value] => 0
)
)
)
[1] => stdClass Object
(
[id] => 2e805552-c887-2b2e-a9e5-518087f3f87a
[module_name] => Project
[name_value_list] => stdClass Object
(
[description] => stdClass Object
(
[name] => description
[value] => I bleed for hockey... I will teach your kid to put them on the boards and take no prisoners!
)
[priority] => stdClass Object
(
[name] => priority
[value] => Secondary
)
[total_years_played_c] => stdClass Object
(
[name] => total_years_played_c
[value] => 7
)
[sport_c] => stdClass Object
(
[name] => sport_c
[value] => Hockey
)
[high_school_exp_c] => stdClass Object
(
[name] => high_school_exp_c
[value] => 3
)
[varsity_exp_c] => stdClass Object
(
[name] => varsity_exp_c
[value] => 2
)
[hand_right_c] => stdClass Object
(
[name] => hand_right_c
[value] => 0
)
[hand_left_c] => stdClass Object
(
[name] => hand_left_c
[value] => 1
)
[foot_right_c] => stdClass Object
(
[name] => foot_right_c
[value] => 1
)
[foot_left_c] => stdClass Object
(
[name] => foot_left_c
[value] => 0
)
[specialskills_c] => stdClass Object
(
[name] => specialskills_c
[value] =>
)
[varsity_starter_c] => stdClass Object
(
[name] => varsity_starter_c
[value] => 0
)
)
)
)
[relationship_list] => Array
(
)
)
Here is the PHP that I am using. For now, I'm just wanting to echo the name of sport_c (one should be Hockey, the other should be Soccer)
<?
foreach($response->entry_list as $sports) {
if(!empty($sports->name_value_list->sport_c)) {
$sport_list = $sports->name_value_list->sport_c;
$sport_name = $sport_list->value;
}
}
echo $sport_name;
?>
Put the echo statement within the foreach loop:
foreach($response->entry_list as $sports) {
if(!empty($sports->name_value_list->sport_c)) {
$sport_list = $sports->name_value_list->sport_c;
$sport_name = $sport_list->value;
}
echo $sport_name;
}

Categories