Can't get why usort() turns array into 1
Here is code of my sorting callback method in SomeClass
protected $_sortKey = '';
public function setSortKey($keyname)
{
$this->_sortKey = $keyname;
}
public function sortByKeyValue($a, $b)
{
$key = $this->_sortKey;
if ($a->$key == $b->$key) {
return 0;
}
return ($a->$key < $b->$key) ? -1 : 1;
}
Here is code where sorting takes place
$someObj = new SomeClass();
$someObj->setSortKey('name');
$sorted_stuff = usort($stuff_to_sort, array($someObj, 'sortByKeyValue'));
where $stuff_to_sort is:
Array
(
[0] => stdClass Object
(
[id] => 57
[status] => ACTIVE
[updated] => 2010-09-17T12:16:25Z
[name] => Windows Server 2008 SP2 x64 - MSSQL2K8R2
)
[1] => stdClass Object
(
[id] => 62
[status] => ACTIVE
[updated] => 2010-10-19T17:16:55Z
[name] => Red Hat Enterprise Linux 5.5
)
)
and $sorted_stuff gets value 1 instead of sorted array. What is wrong ?
PHP 5.2.17
see http://docs.php.net/function.usort:
bool usort ( array &$array , callback $cmp_function )
The sorted array is not the return value. usort() alters the array you're passing as the first argument.
Related
I want sorting Teams list by "terminland_days" value
I read same question in Stack Overflow https://stackoverflow.com/a/38237197/5006328 but still have problem on this.
This is my PHP (PHP >=7.4) code:
public function display($tpl = null) {
// myval get from other model
//print_r ($myval);
$myval = Array
(
[0] => stdClass Object
(
[id] => 1
[state] => 1
[teams] => {"teams0":{"name":"Jhon","terminland_days":"3"},"teams1":{"name":"Alex","terminland_days":"2"}}
[distance] => 5839.5147520164
)
[1] => stdClass Object
(
[id] => 2
[state] => 1
[teams] => {"teams0":{"name":"Jeff","terminland_days":"12"},"teams1":{"name":"Fred","terminland_days":"1"}}
[distance] => 5839.5147520164
)
);
foreach ($myval as $item) {
$paramsteam = json_decode($item->teams);
foreach ($paramsteam as $team) {
// i want sorting Teams as "terminland_days" value
usort($team, "compare_func");
// error ==> Warning: usort() expects parameter 1 to be array, object given
echo $team->terminland_days;
}
}
}
public function compare_func($a, $b)
{
if ($a->terminland_days == $b->terminland_days) {
return 0;
}
return ($a->terminland_days < $b->terminland_days) ? -1 : 1;
// You can apply your own sorting logic here.
}
as I understand, I must use usort, please help me how I can do it?
When print_r ($team); output:
stdClass Object
(
[name] => Jhon
[terminland_days] => 3
)
stdClass Object
(
[name] => Alex
[terminland_days] => 2
)
stdClass Object
(
[name] => Jeff
[terminland_days] => 12
)
stdClass Object
(
[name] => Fred
[terminland_days] => 1
)
After a few hours of scrutiny, I realized that the best way was to first convert the object to an array and then sort it. so :
$paramsteam = json_decode($item->teams,true);
usort($paramsteam, function ($item1, $item2) {
return $item1['terminland_days'] <=> $item2['terminland_days'];
});
foreach ($paramsteam as $team) {
echo $team['terminland_days'];
}
also #Nico haase thank you
I've got an object, containing an array of objects, containing an array of values:
stdClass Object (
[devices] => Array (
[0] => stdClass Object (
[location] => 1
[delegate] =>
[type] => 1
[id] => 1234
[IP] => 1.2.3.4
[name] => host1
[owner] => user6
[security] => 15
)
[1] => stdClass Object (
[location] => 2
[delegate] =>
[type] => 1
[id] => 4321
[IP] => 4.3.2.1
[name] => host2
[owner] => user9
[security] => 15
)
)
)
I want to extract just the id and name into an array in the form of:
$devices['id'] = $name;
I considered using the array_map() function, but couldn't work out how to use it... Any ideas?
This will generate you a new array like I think you want
I know you says that delegate is an object but the print does not show it that way
$new = array();
foreach($obj->devices as $device) {
$new[][$device->id] = $device->name;
}
Would something like this not work? Untested but it cycles through the object structure to extract what I think you need.
$devices = myfunction($my_object);
function myfunction($ob){
$devices = array();
if(isset($ob->devices)){
foreach($ob->devices as $d){
if(isset($d->delegate->name && isset($d->delegate->id))){
$devices[$d->delegate->id] = $d->delegate->name;
}
}
}
return($devices);
}
Im usually using this function to generate all child and parent array stdclass / object, but still make key same :
function GenNewArr($arr=array()){
$newarr = array();
foreach($arr as $a=>$b){
$newarr[$a] = is_object($b) || is_array($b) ? GenNewArr($b) : $b ;
}
return $newarr;
}
i have tried both ksort and asort but in both cases all always shows at bottom..
but i want to display array of index 'all' at top then numeric fields should be displayed.
Actually i am adding that key manually.
$result['all'] = new stdClass();
$result['all']->DisciplinaryAction = 'All';
$result['all']->DisciplinaryActionID = 0;
i tried ksort($result) and also tried asort($result) but in both cases text/string always arranged to bottom..
Array
(
[0] => stdClass Object
(
[DisciplinaryAction] => counseling
[DisciplinaryActionID] => 1
)
[1] => stdClass Object
(
[DisciplinaryAction] => verbal warning
[DisciplinaryActionID] => 2
)
[2] => stdClass Object
(
[DisciplinaryAction] => written warning
[DisciplinaryActionID] => 3
)
[3] => stdClass Object
(
[DisciplinaryAction] => suspension
[DisciplinaryActionID] => 4
)
[4] => stdClass Object
(
[DisciplinaryAction] => termination
[DisciplinaryActionID] => 5
)
[all] => stdClass Object
(
[DisciplinaryAction] => All
[DisciplinaryActionID] => 0
)
)
See How can I sort arrays and data in PHP?.
The much more sensible way to do this, rather than sorting, is probably just to add the key to the beginning of the array directly:
$arr = array_merge(array('all' => new stdClass), $arr);
You can use uasort, uksort or usort to define how this should be handled.
http://php.net/manual/en/array.sorting.php
EDIT : Here's a comparison function for uksort
function cmp($a, $b)
{
if ($a == $b)
return 0;
else if (is_string($a))
return -1;
else if (is_string($b))
return 1;
else
return ($a < $b) ? -1 : 1;
}
I have this simple array $tree in PHP that I need to filter based on an array of tags matching those in the array.
Array
(
[0] => stdClass Object
(
[name] => Introduction
[id] => 798162f0-d779-46b6-96cb-ede246bf4f3f
[tags] => Array
(
[0] => client corp
[1] => version 2
)
)
[1] => stdClass Object
(
[name] => Chapter one
[id] => 761e1909-34b3-4733-aab6-ebef26d3fcb9
[tags] => Array
(
[0] => pro feature
)
)
)
I tried using an anonymous function like so:
$selectedTree = array_filter($tree, function($array) use ($selectedTags){
return in_array($array->tags, $selectedTags, true);
});
$selectedTags:
Array
(
[0] => client corp
)
The above is returning empty when I'd expect item 1 to be returned. No error thrown. What am I missing?
In case of in_array($neddle, $haystack). the $neddle must need to be a String, but you're giving an array that is why its not behaving properly.
But if you like to pass array as value of $selectedTags then you might try something like below:
$selectedTree = array_filter($tree, function($array) use ($selectedTags){
return count(array_intersect($array->tags, $selectedTags)) > 0;
});
Ref: array_intersect
If I am reading the question correctly, you need to look at each object in $tree array and see if the tags property contains any of the the elements in $selectedTags
Here is a procedural way to do it.
$filtered = array();
foreach ($tree as $key => $obj) {
$commonElements = array_intersect($selectedTags, $obj->tags);
if (count($commonElements) > 0) {
$filtered[$key] = $obj;
}
}
I was going to also post the functional way of doing this but, see thecodeparadox's answer for that implementation.
I have read some similar issues here but unfortunately find the solution for my case.
Some part of the output for an API connection is as;
stdClass Object (
[page] => 0
[items] => 5
[total] => 5
[saleItems] => stdClass Object (
[saleItem] => Array (
[0] => stdClass Object (
[reviewState] => approved
[trackingDate] => 2013-11-04T09:51:13.420+01:00
[modifiedDate] => 2013-12-03T15:06:39.240+01:00
[clickDate] => 2013-11-04T09:06:19.403+01:00
[adspace] => stdClass Object (
[_] => xxxxx
[id] => 1849681
)
[admedium] => stdClass Object (
[_] => Version 3
[id] => 721152
)
[program] => stdClass Object (
[_] => yyyy
[id] => 10853
)
[clickId] => 1832355435760747520
[clickInId] => 0
[amount] => 48.31
[commission] => 7.25
[currency] => USD
[gpps] => stdClass Object (
[gpp] => Array (
[0] => stdClass Object (
[_] => 7-75
[id] => z0
)
)
)
[trackingCategory] => stdClass Object (
[_] => rers
[id] => 68722
)
[id] => 86erereress-a9e4-4226-8417-a46b4c9fd5df
)
)
)
)
Some strings do not include gpps property.
What I have done is as follows
foreach($sales->saleItems->saleItem as $sale)
{
$status = $sale->reviewState;
if(property_exists($sale, gpps))
{
$subId = $sale->gpps->gpp[0]->_;
}else{
$subId = "0-0";
}
}
What I want is I the gpps property is not included in that string $subId stored as 0-0 in db, otherwise get the data from the string. But it doesn't get the strings without gpps.
Where is my mistake?
Change
if(property_exists($sale, gpps))
with
if(property_exists($sale, "gpps"))
notice how now gpps is passed as string, as per the signature of the property_exists function:
bool property_exists ( mixed $class , string $property )
This function checks if the given property exists in the specified class.
Note:
As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.
property_exists is the method designed for this purpose.
bool property_exists ( mixed $class , string $property )
This function checks if the given property exists in the specified class.
Note:
As opposed with isset(), property_exists() returns TRUE even if the property has the value NULL.
Try a simple hack and use count, since the property contains an array, and I guess, that count(array) == 0 is the same case as when the property is not set.
foreach($sales->saleItems->saleItem as $sale)
{
$status = $sale->reviewState;
if(#count($sale->gpps->gpp) && count($sale->gpps->gpp) > 0)
{
$subId = $sale->gpps->gpp[0]->_;
}else{
$subId = "0-0";
}
}
Sure, this is not the most beautiful solution, but since the php-function do not work as expected, I thought a bit more pragmatic.
Another way , get_object_vars
$obj = new stdClass();
$obj->name = "Nick";
$obj->surname = "Doe";
$obj->age = 20;
$obj->adresse = null;
$ar_properties[]=get_object_vars($obj);
foreach($ar_properties as $ar){
foreach ($ar as $k=>$v){
if($k =="surname"){
echo "Found";
}
}
}