strcmp equivelant for integers (intcmp) in PHP
Solution 1
Sort your data with:
function sortScripts($a, $b)
{
return $a['order'] - $b['order'];
}
Use $b-$a if you want the reversed order.
If the numbers in question exceed PHP's integer range, return ($a < $b) ? -1 : (($a > $b) ? 1 : 0)
is more robust.
Solution 2
Purely as some additional information, there has been an accepted RFC for this (https://wiki.php.net/rfc/combined-comparison-operator).
So, the comparison function would be along the lines of ...
<?php
$data = [...];
usort($data, function($left, $right){ return $left <=> $right; });
?>
A few really nice feature here is that the comparison is done in exactly the same way as all other comparisons. So type juggling will happen as expected.
As yet, there is no magic __forCompare() like method to allow an object to expose a comparison value. The current proposal (a different RFC) is to have each object be injected into every other object during the comparison so that it does the comparison - something which just seems odd to me - potential opportunity for recursion and stack overflow ... ! I would have thought either injecting the type of object for comparison (allowing an object the ability to represent appropriate values depending upon the type of comparison) or a blind request for a value that the object can serve up for comparison, would have been a safer solution.
Not yet integrated into PHP-NG (PHP 7 at the moment), but hopefully will be soon.
Solution 3
why reinventing the wheel? http://php.net/manual/en/function.strnatcmp.php
echo strnatcmp(1, 2) . PHP_EOL; // -1
echo strnatcmp(10, 2) . PHP_EOL; // 1
echo strnatcmp(10.5, 2) . PHP_EOL; // 1 - work with float numbers
echo strnatcmp(1, -2) . PHP_EOL; // 1 - work with negative numbers
Test it here: https://3v4l.org/pSANR
Solution 4
You could use
function intcmp($a,$b)
{
return ($a-$b) ? ($a-$b)/abs($a-$b) : 0;
}
Although I don't see the point in using this function at all
Solution 5
Does it have to be +1 and -1? If not, just return (int) $a - (int) $b
. I don't like the divide that someone else recommended, and there's no need to check for all three cases. If it's not greater and not equal, it must be less than.
return (int) $a > (int) $b ? 1 : (int) $a == (int) $b ? 0 : -1;
Comments
-
Chase Wilson almost 2 years
So we got this function in PHP
strcmp(string $1,string $2) // returns -1,0, or 1;
We Do not however, have an intcmp(); So i created one:
function intcmp($a,$b) { if((int)$a == (int)$b)return 0; if((int)$a > (int)$b)return 1; if((int)$a < (int)$b)return -1; }
This just feels dirty. What do you all think?
this is part of a class to sort Javascripts by an ordering value passed in.
class JS { // array('order'=>0,'path'=>'/js/somefile.js','attr'=>array()); public $javascripts = array(); ... public function __toString() { uasort($this->javascripts,array($this,'sortScripts')); return $this->render(); } private function sortScripts($a,$b) { if((int)$a['order'] == (int)$b['order']) return 0; if((int)$a['order'] > (int)$b['order']) return 1; if((int)$a['order'] < (int)$b['order']) return -1; } .... }
-
FrustratedWithFormsDesigner about 14 years@Andy E's head: I'm guessing the motivation was a function that produced similar results to
strcmp
, but I'd have to understand the scenario that led to that idea. -
Chase Wilson about 14 yearsThe idea was to aid in sorting an array of a javascripts multi-dimensional array.
-
Chase Wilson about 14 yearsThis worked like a charm! Do you think it works within the context of the class? Or would there be a better implementation? I haven't found a good standard for sorting multi-dimensional arrays yet!!
-
user2012801 about 14 yearsIt's clever oneliner and all, but 1 line is not always more simple than 3. I would be scratching my head if I came across this code just to realize 5 minutes later than all it does is returns +1/0/-1 with all those divisions and modulus. I would just go with original version tbh.
-
Chase Wilson about 14 yearsI had to use ($b-$a)*-1 for reverse order. but I digress. Thanks!
-
nico almost 11 yearsYou'd be scratching your head if you came across a subtraction and a division? Seriously?
-
aioobe over 10 yearsThis implementation is broken just as in many other languages.
-
etherice over 10 yearsTo clarify what @aioobe said, this implementation breaks if the integer exceeds php's integer range (64-bit signed) and is implicitly converted to a floating-point value. Therefore, while
($a - $b)
is obviously much faster, it is not as robust as($a < $b) ? -1 : (($a > $b) ? 1 : 0)
which works in all cases. -
msun almost 9 yearsIMO stacking ternary operators is poor practice. In this case, we have an issue with order of operations. Correction: return (int) $a > (int) $b ? 1 : ( (int) $a == (int) $b ? 0 : -1 );
-
tomlogic almost 9 yearsDoes PHP have different order of operators than C? How else would the interpreter parse this statement without the added parentheses?
-
MazeChaZer about 7 yearsYes, the ternary operator associativity in PHP is broken: phpsadness.com/sad/30
-
Katrina over 6 yearsThis also works for all cases when either just the first or second parameter is a string.
-
Jon Marnock about 5 yearsmin(max($a - $b, -1), 1) works well for integers, but if you need to deal with floats as well and you want to have the range >-1... < 0 > .. < 1 map to -1 or 1 the above nested ternary is probably still better.
-
ToolmakerSteve almost 4 yearsCringeworthy. An abs, a divide, and two subtracts, to implement a trivial, commonplace function? Please, just do the obvious, like everyone else. Your future code readers will thank you.
-
jinyong lee over 3 yearsThis breaks also on (small) decimal numbers. So, better use a more robust version.
-
Gábor over 2 yearsSorry, but is this a joke? You have two numbers, and you compare them by converting them to strings, then the function converts them back to integers and compares them, just as you would have done it yourself in the first place.
-
mickmackusa about 2 years@ChaseWilson sorting multidimensional arrays is super simple/elegant with
usort()
and the spaceship operator. -
mickmackusa about 2 yearsI would never use either of these snippets. Both can be replace by using the spaceship operator -- no reason to have separate techniques at all.
-
mickmackusa about 2 yearsFortunately the spaceship (three-way comparison) operator was invented and this answer is not attractive for any reason.
-
mickmackusa about 2 yearsThe subtraction and the ternary workaround are no longer necessary with the invention of the spaceship operator.