PHP usort Multi-dimensional array - php

I'm having trouble getting usort to work and not sure what I'm missing. Below is an example of my array. I want to sort the array based on the value of the sort key.
Array
(
[0] => Array
(
[sort] => 1520546956
[row] => Data lives here
)
[1] => Array
(
[sort] => 1521047928
[row] => Data lives here
)
[2] => Array
(
[sort] => 1520525366
[row] => Data lives here
)
[3] => Array
(
[sort] => 1520525227
[row] => Data lives here
)
My code to try and sort this is:
foreach ($resultsArray as $record)
{
usort($record['sort'], function($a, $b)
{
if ($a == $b)
{
return 0;
}
return ($a < $b) ? -1 : 1;
});
}
However my code seems to be ineffective as the order of the array isn't changing. I feel like I'm close but can't identify what I'm missing. Thank you for any help!

A different approach to accomplish the same functionality is to use array_multisort with the desired combination of sorting flags.
Dataset:
$resultsArray = array(
array('sort'=>1520546956, 'row'=>'row 0 data'),
array('sort'=>1521047928, 'row'=>'row 1 data'),
array('sort'=>1520525366, 'row'=>'row 2 data'),
array('sort'=>1520525227, 'row'=>'row 3 data')
);
array_multisort Example:
$sortValues = array_column($resultsArray, 'sort');
array_multisort($sortValues, SORT_ASC, $resultsArray);
print_r($resultsArray);
Results: https://3v4l.org/NpVIc
Array
(
[0] => Array
(
[sort] => 1520525227
[row] => row 3 data
)
[1] => Array
(
[sort] => 1520525366
[row] => row 2 data
)
[2] => Array
(
[sort] => 1520546956
[row] => row 0 data
)
[3] => Array
(
[sort] => 1521047928
[row] => row 1 data
)
)
Alternatively you can still use usort, but in your function, you need to retrieve the associated array key named sort in order to compare the values.
usort Example:
usort($resultsArray, function($a, $b) {
if ($a['sort'] == $b['sort']) {
return 0;
}
return ($a['sort'] < $b['sort'] ? -1 : 1);
});
print_r($resultsArray);
Results: https://3v4l.org/5nfbc

Modified code to reflect the below as suggested:
usort($resultsArray, function($a, $b) { /* compare $a['sort'] and $b['sort'] */ }
Working perfectly.

$record['sort'] would have to be an array for that to work. Yet still, it does nothing.
I'm pretty sure you want to do this:
<?php
$multiArray = array(
array('sort'=>1520546956, 'row'=>'row 0 data'),
array('sort'=>1521047928, 'row'=>'row 1 data'),
array('sort'=>1520525366, 'row'=>'row 2 data'),
array('sort'=>1520525227, 'row'=>'row 3 data'));
foreach($multiArray as $a){
$numArray[] = $a['sort'];
}
asort($numArray, SORT_NUMERIC);
foreach($numArray as $k => $v){
$resArray[] = $multiArray[$k];
}
print_r($resArray);
?>

It is because php foreach construct works on the copy of the array provided(ie: $resultsArray), where php usort() function references or points to the same array. That is why your code is not working as expected.
If you don't understand this concept I suggest you a good online course by Kevin skoglund (php essential training) in Lynda.com

Related

Sort array with 2 conditions

I am trying to create a golf livescore leaderboard, but am having one issue. I would like to order the array by who has the lowest points, but also, if 2 or more have the same points, order those by which hole they are on.
My initial array looks like this:
Array
(
[0] => Array
(
[userid] => 1301
[holes] => 6
[points] => -2
)
[1] => Array
(
[userid] => 231
[holes] => 5
[points] => 7
)
[2] => Array
(
[userid] => 3421
[holes] => 6
[points] => 7
)
[3] => Array
(
[userid] => 46
[holes] => 6
[points] => 3
)
[4] => Array
(
[userid] => 745
[holes] => 4
[points] => 7
)
)
Now, then I do this to order the array by points:
$sortArray = array();
foreach($playersArray as $person){
foreach($person as $key=>$value){
if(!isset($sortArray[$key])){
$sortArray[$key] = array();
}
$sortArray[$key][] = $value;
}
}
$orderby = "points";
array_multisort($sortArray[$orderby],SORT_ASC,$playersArray);
This orders the array by points, but as you can see, I have 3 players with 7 points but on different holes and would like to order those with same holes so the highest rank is the one on the lowest hole.
Hope this makes sense and any help is appreciated.
Thanks in advance :-)
Use usort.
Example:
usort($playersArray, function ($a, $b) {
if ($a['points'] == $b['points']) {
return $a['holes'] < $b['holes'];
}
return $a['points'] < $b['points'];
});
Change < to > to change sorting order.
Use usort.
This function will sort an array by its values using a user-supplied comparison function. If the array you wish to sort needs to be sorted by some non-trivial criteria, you should use this function.
usort($score, function ($a, $b) {
return $a['points'] - $b['points']
? $a['points'] - $b['points']
: $a['holes'] - $b['holes'];
});
Try this way :
function order_by_points($a, $b){
if ($a['points'] == $b['points'])
// sort the higher points first:
return $a['points'] < $b['points'] ? 1 : -1;
}

PHP select arrays based on value in a multidimensional array

I have an array with the below structure and I need to select the greatest education level from the sub arrays that have selected=>1, the greater the [key] the greater the education level.
anyway to do this with PHP built in array functions?
Array
(
[0] => Array
(
[key] => 0
[selected] => 1
[value] => Highschool diploma
)
[1] => Array
(
[key] => 1
[selected] => 0
[value] => Vocational training
)
[2] => Array
(
[key] => 2
[selected] => 0
[value] => College degree (Outside Quebec)
)
[3] => Array
(
[key] => 3
[selected] => 1
[value] => College degree (Quebec)
)
[4] => Array
(
[key] => 4
[selected] => 1
[value] => Baccalaureate
)
[5] => Array
(
[key] => 5
[selected] => 0
[value] => Masters degree
)
[6] => Array
(
[key] => 6
[selected] => 0
[value] => Doctorate
)
)
PHP >= 5.5.0
To get all the selected keys:
$keys = array_filter(array_column($array, 'selected'));
// or if there can be values other than 0 and 1
$keys = array_keys(array_column($array, 'selected'), '1');
To get the key with the highest value:
$max = max(array_filter(array_column($array, 'selected')));
// or if there can be values other than 0 and 1
$max = max(array_keys(array_column($array, 'selected'), '1'));
array_walk($data, function($el) use(&$ret) {
// or if (empty($ret) ...
if (!isset($ret) || ($el['selected'] >= 1 && $ret['key'] < $el['key']))
$ret = $el;
});
var_dump($ret);
Just do not forget to unset or set $ret = false; //null, etc..
if you want to run this code multiple times :)
If you want to use php built-ins, array_reduce is probably the way to go. Something like this should do the trick:
$result = array_reduce($theArray, function($state, $item) {
if($item['selected'] !== 1) return $state;
if($state === null) return $item;
if($item['key'] > $state['key']) return $item;
return $state;
});
echo $result['value'];
update: I should note that the above only works in PHP 5.3 or later, because it uses anonymous functions, which weren't available in earlier versions of PHP. If you're working with an earlier version, you really should upgrade. But if you can't upgrade, then you'll have to define the function part as a normal stand-alone function, and then pass the name of your function (as a string) in the second argument to array_reduce. This approach is shown in the examples on the doc page for array_reduce.
Sure. Loop through each inner array, and check their values against the one that is currently top. For example: https://eval.in/private/5c5a2ba8015119
$final = array();
foreach($array as $education) {
if($education['selected'] != 1) {
continue;
}
if(isset($final['key']) == FALSE
OR $education['key'] > $final['key']) {
$final = $education;
}
}
echo print_r($final, true);
I've build a test function for you.
Tested and working! Cheers to Baccalaureate!
<?php
// Demo Data
$your_array = array(
array(
'key'=>0,
'selected'=>1,
'value'=>'Highschool diploma'
),
array(
'key'=>1,
'selected'=>0,
'value'=>'Vocational training'
),
array(
'key'=>2,
'selected'=>0,
'value'=>'College degree (Outside Quebec)'
),
array(
'key'=>3,
'selected'=>1,
'value'=>'College degree (Quebec)'
),
array(
'key'=>4,
'selected'=>1,
'value'=>'Baccalaureate'
),
array(
'key'=>5,
'selected'=>0,
'value'=>'Masters degree'
),
array(
'key'=>6,
'selected'=>0,
'value'=>'Doctorate'
)
);
// Actual function
$array_count = (count($your_array)-1);
$highest_education = 'Nothing found.';
for($i=$array_count;$i>0;$i--)
{
if($your_array[$i]['selected']==1)
{
$highest_education = $your_array[$i]['value'];
break;
}
}
// Testing output
echo $highest_education;
?>

compare multi-dimensional arrays and return they keys who's values are different in php from the first array

I have two multi-dimensional array I want to take only those array whose
key values are different from the first array
Here is my two array:
$array1 = Array
(
[0] => Array
(
[id] => 1
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => uouuououou
[job_type] => ouuou
[job_title] => u
[job_appointment_date] => 2013-07-15
[job_duration] => ouu
)
[1] => Array
(
[id] => 2
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => DDC
[job_type] => Manger
[job_title] => Manager
[job_appointment_date] => 2013-07-17
[job_duration] => one year
)
)
and this is my second array
$array2 = Array
(
[0] => Array
(
[id] => 1
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => uouuououou
[job_type] => ouuou
[job_title] => u
[job_appointment_date] => 2013-07-15
[job_duration] => ouu
)
[1] => Array
(
[id] => 2
[serial] => k-0001
[u_rec_id] => 1
[employer_office] => ouo
[job_type] => uououo
[job_title] => udds
[job_appointment_date] => 2013-07-17
[job_duration] => uo
)
);
I tried array_diff and array_diff_assoc it also not worked for me
i get this error
A PHP Error was encountered
Severity: Notice
Message: Array to string conversion
Filename: history/home.php
Line Number: 729
Something like this should get you there, depending on what exactly you want:
$diff = array_udiff($array1, $array2, function (array $a, array $b) {
return (int)array_diff($a, $b);
});
Adjust the comparison function to compare what exactly you want to compare.
http://php.net/array_udiff
foreach, array_unique and possibly array_udiff should help you here.
PHP Manual:
Unique Arrays
Data Comparison
For Each
For a simple array:
$result = array_unique($array);
In your case there's a function from PHP Manual for this:
<?php
function specified_array_unique($array, $value)
{
$count = 0;
foreach($array as $array_key => $array_value)
{
if ( ($count > 0) && ($array_value == $value) )
{
unset($array[$array_key]);
}
if ($array_value == $value) $count++;
}
return array_filter($array);
}
?>
There's been a post that is similar to what you're asking;
Stack Overflow - array_udiff

How to sort nested PHP array

Can anyone tell me how to sort an array by key?
I want to sort this array by price.
this is my input array format
Array
(
[0] => Array
(
[house_data] => Array
(
[id] => 532
[max_person] => 8
[max_bedrooms] => 4
)
[image] => uploads/123.jpg
[price] => 1950
)
[1] => Array
(
[house_data] => Array
(
[id] => 531
[max_person] => 8
[max_bedrooms] => 5
)
[image] => uploads/1234.jpg
[price] => 1495
)
}
Try usort (http://php.net/manual/en/function.usort.php)
You should have something like:
function cmp($a, $b)
{
if ($a['price'] == $b['price']) {
return 0;
}
return ($a['price'] < $b['price']) ? -1 : 1;
}
usort($table, "cmp");
For making it one dimensional use serialize($array) function , it goes like this :$a = array() ; //your multidimensional array$b = array(); //output arrayforeach ($a as $key=>$value){ $b[] = serialize($value);}echo $b ;
Use the array_multisort() function for multidimensional array sorting.

help sorting this array

So I am looking to sort the multi dimensional array below by "fk_page_id" ascending. Does anyone have any pointers. I think usort() is where I have to look but it seems like I cant find anyone with my specific array structure.
Array
(
[0] => Array
(
[title] => subpage of subpage!
[id] => 5
[long_title] =>
[fk_page_id] => 4
)
[1] => Array
(
[title] => about us subpage
[id] => 4
[long_title] =>
[fk_page_id] => 2
)
[2] => Array
(
[title] => about us
[id] => 2
[long_title] =>
[fk_page_id] => 1
)
)
function cmp($a, $b) {
if($a['fk_page_id'] == $b['fk_page_id']) {
return 0;
} else {
return $a['fk_page_id'] < $b['fk_page_id'] ? -1 : 1;
}
}
usort($yourarray, 'cmp');
if you're using PHP 5.3+:
define(ASC,1);
define(DESC,-1);
function colsort($array,$col,$order=ASC) {
usort(
$array,
function($a,$b) use($col,$order) {
return strcmp($a[$col],$b[$col])*$order;
}
);
return $array;
}
colsort($x,'fk_page_id');

Categories