PHP usort() for Dummies - php

Sorry for posting this totally confused n00b question, but I do not get around the arcane usort() explanation in the manual.
<?php
function cmp($a, $b)
{
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
$a = array(3, 2, 5, 6, 1);
usort($a, "cmp");
foreach ($a as $key => $value) {
echo "$key: $value\n";
}
?>
When i echo $a in the cmp function I get a 5156120 as key for the first item, when I echo $b I get 2535630.
That is basically my whole question: What is $a and $b in the callback function?
But if you want to really help, please give a "line-by-line" explanation about what is happening.
HAPPY NYE!!!
(I tried to add the tags "noob" and "confused", need 1400 reputation more though. ; )

$a and $b are the two values being compared in the custom comparison function.
If you have array( 3, 2, 5, 6, 1) that you're sorting, you'll find cmp() compares 3 to 2, 2 to 5, 5 to 6, etc. until the values are properly sorted.
So, for example:
<?php
function cmp($a, $b)
{
echo "$a :compared with: $b <br/>";
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
$arr = array(3, 2, 5, 6, 1);
usort($arr, "cmp");
outputs:
5 :compared with: 2
5 :compared with: 3
5 :compared with: 6
1 :compared with: 5
2 :compared with: 1
3 :compared with: 2
I see usort() usually used to make much more intricate comparisons, where you need to break apart the value and compare just a piece of it, or assign custom priorities (e.g. sort by title President, Vice President, Secretary, etc., by priority and not by alphanumeric value)

Related

How to view the steps of the usort() in PHP?

This is the Example #1 from the php.net usort() page:
<?php
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
$a = array(3, 2, 5, 6, 1);
usort($a, "cmp");
foreach ($a as $key => $value) {
echo "$key: $value\n";
}
?>
The usort function takes the values within the array as pairs ($a-$b; so this is - 3-2, 2-5, 5-6, 6-1) and moves the $b value depending on whether the cmp() function returns -1, 0 or 1. If it is -1 the $b gets moved down (within a current pair), if it is 0 it stays in the same place and if it is 1 it gets moved up. This is how this is suppose to be working based on the top comment from the php.net manual usort() page.
Is there any way to see how this works step by step (the sorting process)? Am I able to see it or is it only possible to see the final result after the sorting is done? I want to understand fully how this process works.
Using some debug output in your comparison function you can only see the comparisons that PHP does, but can't see intermediate states of the array.
But the algorithm used in usort is well known - it's QuickSort ( Which sort algorithms does PHP's usort apply? ).
You can see its vizualisation at http://www.algomation.com/algorithm/quick-sort-visualization (or just google "quicksort algorithm visualization")

Spaceship operator confusion in PHP7 (return -1)

I am pretty new to PHP7 and so far it seems great and powerful. I have been using PHP5.6 so I started understanding the usage of spaceship operator <=>. But somehow I couldn't get the logic that statement returns -1. I know the point of returning to 0 or 1 which are false or true. Can anyone clarify the usage of return -1?
Function normal_sort($a, $b) : int
{
if( $a == $b )
return 0;
if( $a < $b )
return -1;
return 1;
}
function space_sort($a, $b) : int
{
return $a <=> $b;
}
$normalArray = [1,34,56,67,98,45];
//Sort the array in asc
usort($normalArray, 'normal_sort');
foreach($normalArray as $k => $v)
{
echo $k.' => '.$v.'<br>';
}
$spaceArray = [1,34,56,67,98,45];
//Sort it by spaceship operator
usort($spaceArray, 'space_sort');
foreach($spaceArray as $key => $value)
{
echo $key.' => '.$value.'<br>';
}
You have three possibilities when comparing the two values that are passed to a comparison function: $a < $b, $a == $b, or $a > $b. So you need three distinct return values and PHP has chosen the integers: -1, 0, and 1. I guess it could just as easily be strings lesser, equal and greater or integers 5, 7 and 9 or any combination, but it's not.
From the manual usort()
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
$a < $b return -1
$a == $b return 0
$a > $b return 1
This is NOT how types work in PHP, but you can think of it like this: is $a > $b? where -1 means false, 1 means true and 0 means neither (equal).

Name of natural comparison function in php?

I want to do the intersection between two multidimensional arrays in php 5. E.g:
$a = array(array(), array(1), array(2));
$b = array(array(), array(0), array(2));
I naturally try:
array_intersect($a, $b)
But it gives me Notice because of array to string conversion. As a workaround, I want to precise the comparison function using uintersect:
array_uintersect($a, $b, function($x, $y){return $x == $y ? 0 : ( $x < $y ? -1 : 1 );})
And it works. But this is kind of ugly. My question is simple, is there a built-in natural comparison function which works on array and which I could use as callback function like in:
array_uintersect($a, $b, 'natcmp')
Thank you!

PHP. How does user defined compare function work?

Example:
<?php
function cmp($a, $b)
{
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
$a = array(3, 2, 5, 6, 1);
usort($a, "cmp");
foreach ($a as $key => $value) {
echo "$key: $value\n";
}
?>
Result
0: 1
1: 2
2: 3
3: 5
4: 6
in the user defined compare function 'cmd', it has two arguments, $a & $b.
What do the first and second argument represent? Are they array[x] and array[x+1] ?
They are just two of the elements from the array being sorted, not necessarily neighbours. usort performs some sort algorithm (see http://en.wikipedia.org/wiki/Sort_algorithm#Comparison_of_algorithms), which involves comparing various pairs of elements to determine their order. It uses your callback function to determine this.

min function that ignores negative values in php

I have three numbers:
$a = 1
$b = 5
$c = 8
I want to find the minimum and I used the PHP min function for that. In this case it will give 1.
But if there is a negative number, like
$a = - 4
$b = 3
$c = 9
now the PHP min() should give $b and not $a, as I just want to compare positive values, which are $b and $c. I want to ignore the negative number.
Is there any way in PHP? I thought I will check if the value is negative or positive and then use min, but I couldn't think of a way how I can pass only the positive values to min().
Or should I just see if it's negative and then make it 0, then do something else?
You should simply filter our the negative values first.
This is done easily if you have all of them in an array, e.g.
$a = - 4;
$b = 3;
$c = 9;
$values = array($a, $b, $c);
$values = array_filter($values, function($v) { return $v >= 0; });
$min = min($values);
print_r($min);
The above example uses an anonymous function so it only works in PHP >= 5.3, but you can do the same in earlier versions with
$values = array_filter($values, create_function('$v', 'return $v >= 0;'));
See it in action.
$INF=0x7FFFFFFF;
min($a>0?$a:$INF,$b>0?$b:$INF,$c>0?$c:$INF)
or
min(array_filter(array($a,$b,$c),function($x){
return $x>0;
}));
http://codepad.org/DVgMs7JF
<?
$test = array(-1, 2, 3);
function removeNegative($var)
{
if ($var > 0)
return $var;
}
$test2 = array_filter($test, "removeNegative");
var_dump(min($test2));
?>

Categories