Sort array by value of a specific key [duplicate] - php

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 7 years ago.
I've got an array as such:
$currentTerm = array(
'name' => $term->name,
'weight' => $term->weight
);
I'd like to sort the entire array by the weight key. I can't figure out how to accomplish this. Any thoughts or should I write a custom function for this?
P.S Some weights can be the same; so storing them as a key isn't an option. And it's multidimensional with a children key which is filled recursively the same way as above.

You can create a custom sorting method usort().
It would work similarly to this:
usort($array, function($a,$b) {
if($a->weight === $b->weight) return 0;
return ($a->weight < $b->weight) ? -1 : 1;
});
If people from the PHP7 future come here, they can just use this (spaceships!):
usort($array, function($a,$b) {
return $a->weight <=> $b->weight;
});
A full (and cumbersome) example for pre-PHP7 would be:
<?php
class Obj {
public $name;
public $weight;
function __construct($name,$weight) {
$this->name = $name;
$this->weight = $weight;
}
}
$array = array(
new Obj("A",3),
new Obj("B",10),
new Obj("C",8),
);
usort($array, function($a,$b) {
if($a->weight == $b->weight) return 0;
return ($a->weight < $b->weight) ? -1 : 1;
});
print_r($array);
?>

Take a look at array_multisort()
$weight = array();
foreach ($currentTerm as $key => $row)
{
$weight[$key] = $row['weight'];
}
then
array_multisort($weight, SORT_ASC, $currentTerm);
or
array_multisort($weight, SORT_DESC, $currentTerm);

You can try this code:
//define a comparison function
function cmp($a, $b) {
if ($a['status'] == $b['status']) {
return 0;
}
return ($a['status'] < $b['status']) ? -1 : 1;
}
usort($array, "cmp");

Related

Laravel sorting associative arrays

I am trying to sort an array based on a specific key but it's not working. The array is below when in JSON format. I want to sort it in ascending order by id_question.
This is what I have done so far:
public function compare($ar1, $ar2){
if ($ar1['id_question']<$ar2['id_question']) {
return 1;
}else {
return -1;
}
}
Call the sort function:
uasort($related, Array ($this, 'compare'));
This is what it returns:
As you can see, it doesn't apply the sort.
It's done
here is solution
usort($related, function($a, $b){
if ($a['id_question'] < $b['id_question']) {
return -1;
}else {
return 1;
}
});
I hope this helps -
$listItem = collect($related)->sortBy('id_question')->toArray();
Please try:
$related = collect($related)->sortBy('id_question')->all();

Sorting database values using usort and Sortby(collection method)

I am trying to use usort and sortby to basically after the code below is
1. sort $featureLists by 'feature_sort_order'
2. loop over each $featureList and reset sort order to integer a contiguous value
my Petitions table has feature_sort_order column having values 1 to 6
i used this part of code in controller :
$featureList = Petition::getFeaturedPetitions();
$Petition->featured_sort_order = Input::get('dropdown_menu_list');
foreach($featureList as $featureLists)
{
if($featureLists->feature_sort_order >= $Petition->featured_sort_order && $featureLists->id != $Petition->id)
{
$featureLists->feature_sort_order += 1;
}
}
Here what i trying to do is select a value from dropdown menu and to change current item position before selected item.
i have tried few things like this but doesn't work out :
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
function sortBy(&$items, $key) {
if (is_array($items)) {
return usort($items, function($a, $b) use ($key) {
return cmp($a[$key], $b[$key]);
});
}
return false;
}
sortBy($featureList, 'featured_sort_order');
// foreach($featureLists->feature_sort_order as featureOrder)
// {
// }

Sort after an array value that is child of the array

I tried to search and found this:
Sort an array by a child array's value in PHP
But the function does not work in my case:
$sorted = array();
foreach($players as $player)
{
$p = Model::factory('user');
$p->load($player['id']);
$sorted[] = array('id' => $player['id'], 'username' => $p->get_username());
}
How can i sort the array alphabetic after the username?
The function,
function cmp($a, $b) {
if ($a['username'] == $b['username']) {
return 0;
}
return ($a['username'] < $b['username']) ? -1 : 1;
}
and then calling usort($sorted,"cmp"); will not work out for me (getting error undefined index[2])..
And is there any way to choose whether it should be sorting descending or ascending?
The 'cmp' function will be:
// $param - the parameter by which you want to search
function cmp(&$a, &$b, $param) {
switch( $param ) {
case 'id':
if ( $a['id'] == $b['id'] ) {
return 0;
}
return ( $a['id'] < $b['id'] ) ? -1 : 1;
break;
case 'username':
// string comparison
return strcmp($a['username'], $b['username']);
break;
}
}
// this is the sorting function by using an anonymous function
// it is needed to pass the sorting criterion (sort by id / username )
usort( $sorted, function( $a,$b ) {
return cmp( $a, $b, 'username');
});
Because the index 2 doesn't exist in your array. You should use $a['username'] or $a['id'], but i guess you want to sort on username so then you would use $a['username'].

Sort multi-dimensional array with usort

The following usort function does not always give the right result since it will only "push" up or down one position relative to the compared item. Thus when performing the sort multiple times the result Yes No Yes Nocan occur.
The function successfully sort field b.
How can I solve this?
array
[0] => array("a"=>"Yes","b"=>"apple"...);
[1] => array("a"=>"Yes","b"=>"banana"...);
[2] => array("a"=>"No","b"=>"lemon"...);
[3] => array("a"=>"No","b"=>"grape"...);
...
current function
function sortAnserDesc($x, $y){
if ( $x['a'] == $y['a'] )
return 0;
else if ( $x['a'] < $y['a'] )
return 1;
else
return -1;
}
I found a very good function on http://www.php.net/manual/en/function.usort.php#103722
And I think you have a general problem.
I try to display the callback function for usort here.
function usortByArrayKey($key, $asc=SORT_ASC) {
$sort_flags = array(SORT_ASC, SORT_DESC);
if (!in_array($asc, $sort_flags))
throw new InvalidArgumentException('sort flag only accepts SORT_ASC or SORT_DESC');
return function(array $a, array $b) use ($key, $asc, $sort_flags) {
if (!is_array($key)) { //just one key and sort direction
if (!isset($a[$key]) || !isset($b[$key])) {
throw new Exception('attempting to sort on non-existent keys');
}
if ($a[$key] == $b[$key])
return 0;
return ($asc == SORT_ASC xor $a[$key] < $b[$key]) ? 1 : -1;
} else { //using multiple keys for sort and sub-sort
foreach ($key as $sub_key => $sub_asc) {
//array can come as 'sort_key'=>SORT_ASC|SORT_DESC or just 'sort_key', so need to detect which
if (!in_array($sub_asc, $sort_flags)) {
$sub_key = $sub_asc;
$sub_asc = $asc;
}
//just like above, except 'continue' in place of return 0
if (!isset($a[$sub_key]) || !isset($b[$sub_key])) {
throw new Exception('attempting to sort on non-existent keys');
}
if ($a[$sub_key] == $b[$sub_key])
continue;
return ($sub_asc == SORT_ASC xor $a[$sub_key] < $b[$sub_key]) ? 1 : -1;
}
return 0;
}
};
}
And to integrate with your code, you might have something like:
Sorting a value only by DESCENDING.
usort($YOUR_ARRAY, usortByArrayKey('a', SORT_DESC));
Sorting a and b.
usort($YOUR_ARRAY, usortByArrayKey(array('a', 'b')));
More on sorting a and b by DESCENDING
usort($YOUR_ARRAY, usortByArrayKey(array('a', 'b')), SORT_DESC);
Hope this help!!
Why don't you directly use strcmp function?
function sortAnserDesc($x, $y){
return strcmp($x['a'],$y['a']);
}

Sort Object in PHP [duplicate]

This question already has answers here:
Sort array of objects by one property
(23 answers)
Closed 3 months ago.
What is an elegant way to sort objects in PHP? I would love to accomplish something similar to this.
$sortedObjectArary = sort($unsortedObjectArray, $Object->weight);
Basically specify the array I want to sort as well as the field I want to sort on. I looked into multidimensional array sorting and there might be something useful there, but I don't see anything elegant or obvious.
Almost verbatim from the manual:
function compare_weights($a, $b) {
if($a->weight == $b->weight) {
return 0;
}
return ($a->weight < $b->weight) ? -1 : 1;
}
usort($unsortedObjectArray, 'compare_weights');
If you want objects to be able to sort themselves, see example 3 here: http://php.net/usort
For php >= 5.3
function osort(&$array, $prop)
{
usort($array, function($a, $b) use ($prop) {
return $a->$prop > $b->$prop ? 1 : -1;
});
}
Note that this uses Anonymous functions / closures. Might find reviewing the php docs on that useful.
You can even build the sorting behavior into the class you're sorting, if you want that level of control
class thingy
{
public $prop1;
public $prop2;
static $sortKey;
public function __construct( $prop1, $prop2 )
{
$this->prop1 = $prop1;
$this->prop2 = $prop2;
}
public static function sorter( $a, $b )
{
return strcasecmp( $a->{self::$sortKey}, $b->{self::$sortKey} );
}
public static function sortByProp( &$collection, $prop )
{
self::$sortKey = $prop;
usort( $collection, array( __CLASS__, 'sorter' ) );
}
}
$thingies = array(
new thingy( 'red', 'blue' )
, new thingy( 'apple', 'orange' )
, new thingy( 'black', 'white' )
, new thingy( 'democrat', 'republican' )
);
print_r( $thingies );
thingy::sortByProp( $thingies, 'prop1' );
print_r( $thingies );
thingy::sortByProp( $thingies, 'prop2' );
print_r( $thingies );
For that compare function, you can just do:
function cmp( $a, $b )
{
return $b->weight - $a->weight;
}
The usort function (http://uk.php.net/manual/en/function.usort.php) is your friend. Something like...
function objectWeightSort($lhs, $rhs)
{
if ($lhs->weight == $rhs->weight)
return 0;
if ($lhs->weight > $rhs->weight)
return 1;
return -1;
}
usort($unsortedObjectArray, "objectWeightSort");
Note that any array keys will be lost.
You could use the usort() function and make your own comparison function.
$sortedObjectArray = usort($unsortedObjectArray, 'sort_by_weight');
function sort_by_weight($a, $b) {
if ($a->weight == $b->weight) {
return 0;
} else if ($a->weight < $b->weight) {
return -1;
} else {
return 1;
}
}
Depending on the problem you are trying to solve, you may also find the SPL interfaces useful. For example, implementing the ArrayAccess interface would allow you to access your class like an array. Also, implementing the SeekableIterator interface would let you loop through your object just like an array. This way you could sort your object just as if it were a simple array, having full control over the values it returns for a given key.
For more details:
Zend Article
PHPriot Article
PHP Manual
function PHPArrayObjectSorter($array,$sortBy,$direction='asc')
{
$sortedArray=array();
$tmpArray=array();
foreach($this->$array as $obj)
{
$tmpArray[]=$obj->$sortBy;
}
if($direction=='asc'){
asort($tmpArray);
}else{
arsort($tmpArray);
}
foreach($tmpArray as $k=>$tmp){
$sortedArray[]=$array[$k];
}
return $sortedArray;
}
e.g =>
$myAscSortedArrayObject=PHPArrayObjectSorter($unsortedarray,$totalMarks,'asc');
$myDescSortedArrayObject=PHPArrayObjectSorter($unsortedarray,$totalMarks,'desc');
You can have almost the same code as you posted with sorted function from Nspl:
use function \nspl\a\sorted;
use function \nspl\op\propertyGetter;
use function \nspl\op\methodCaller;
// Sort by property value
$sortedByWeight = sorted($objects, propertyGetter('weight'));
// Or sort by result of method call
$sortedByWeight = sorted($objects, methodCaller('getWeight'));
Update from 2022 - sort array of objects:
usort($array, fn(object $a, object $b): int => $a->weight <=> $b->weight);
Full example:
$array = [
(object) ['weight' => 5],
(object) ['weight' => 10],
(object) ['weight' => 1],
];
usort($array, fn(object $a, object $b): int => $a->weight <=> $b->weight);
// Now, $array is sorted by objects' weight.
// display example :
echo json_encode($array);
Output:
[{"weight":1},{"weight":5},{"weight":10}]
Documentation links:
usort
spaceship operator (PHP 7.0)
scalar type declaration (PHP 7.0)
return type declaration (PHP 7.0)
arrow function (PHP 7.4)
If you want to explore the full (terrifying) extent of lambda style functions in PHP, see:
http://docs.php.net/manual/en/function.create-function.php

Categories