strcmp equivelant for integers (intcmp) in PHP

41,996

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;
Share:
41,996
Chase Wilson
Author by

Chase Wilson

I think I'm going to puke.

Updated on July 05, 2022

Comments

  • Chase Wilson
    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
    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
    Chase Wilson about 14 years
    The idea was to aid in sorting an array of a javascripts multi-dimensional array.
  • Chase Wilson
    Chase Wilson about 14 years
    This 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
    user2012801 about 14 years
    It'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
    Chase Wilson about 14 years
    I had to use ($b-$a)*-1 for reverse order. but I digress. Thanks!
  • nico
    nico almost 11 years
    You'd be scratching your head if you came across a subtraction and a division? Seriously?
  • aioobe
    aioobe over 10 years
    This implementation is broken just as in many other languages.
  • etherice
    etherice over 10 years
    To 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
    msun almost 9 years
    IMO 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
    tomlogic almost 9 years
    Does PHP have different order of operators than C? How else would the interpreter parse this statement without the added parentheses?
  • MazeChaZer
    MazeChaZer about 7 years
    Yes, the ternary operator associativity in PHP is broken: phpsadness.com/sad/30
  • Katrina
    Katrina over 6 years
    This also works for all cases when either just the first or second parameter is a string.
  • Jon Marnock
    Jon Marnock about 5 years
    min(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
    ToolmakerSteve almost 4 years
    Cringeworthy. 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
    jinyong lee over 3 years
    This breaks also on (small) decimal numbers. So, better use a more robust version.
  • Gábor
    Gábor over 2 years
    Sorry, 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
    mickmackusa about 2 years
    @ChaseWilson sorting multidimensional arrays is super simple/elegant with usort() and the spaceship operator.
  • mickmackusa
    mickmackusa about 2 years
    I 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
    mickmackusa about 2 years
    Fortunately the spaceship (three-way comparison) operator was invented and this answer is not attractive for any reason.
  • mickmackusa
    mickmackusa about 2 years
    The subtraction and the ternary workaround are no longer necessary with the invention of the spaceship operator.