tags:

views:

112

answers:

4

This is my callback for my usort()

public function sortProperties($a, $b) {

        $sortA = inflector::camelize(str_replace('-', '_', $this->sortBy));
        $sortB = inflector::camelize(str_replace('-', '_', $this->sortBy));

        $a = Arr::get($a, $sortA);
        $b = Arr::get($b, $sortB);


        if (is_numeric($a) AND is_numeric($b)) {
            return  $a < $b; 
        } else {
            return strcasecmp($a, $b); 
        }


    }

Usually, when I see the first 2 lines in any of my code, it screams to me: refactor! I guess it's because they are identical.

I know I could make a function getCamelized(), but I don't think I'd use it again outside of this.

Is there a way to turn those 4 lines into 2? Could func_get_args() or array_walk() help me here?

Also, is there anything wrong about this sorting function?

+1  A: 

Is there a way to turn those 4 lines into 2?

    $sortA = $sortB = inflector::camelize(str_replace('-', '_', $this->sortBy));

And for other two lines:

    list($a, $b) = array(Arr::get($a, $sortA), Arr::get($b, $sortB));

As for sort, it seems to be fine at least to me.

Sarfraz
how is $sortA = $sortB and $a = $b going to help?
Ben
`$a = $b = Arr::get($a, $sortA);` Won't this set $a and $b to what $a will be?
alex
@Ben: see my answer again plz
Sarfraz
@Alex: Example: $a = $b = 10; both $a and $b will have value of 10. b is equal to 10 and a is equal to b which is actually 10 making a's value also 10. You can translate it in your own way :)
Sarfraz
@Sarfraz While your first line is identical in functionality to @alex' question, the second line is not (unless `Arr::get` will return the same value for different inputs, which would make it non-sensical).
deceze
@deceze: you are right i think, i did not notice that, thanks
Sarfraz
@Sarfraz Uhmm... What about leaving the second line alone? Please? :o) While technically brilliant, `list(...) = array(...)` is just so much more expensive and harder to read. If you insist on writing it on one line, just do `$a = ...; $b = ...;`. It's virtually impossible to make this any more concise without obfuscating it. :-)
deceze
@deceze: "What about leaving the second line alone?" yeah that is good way to go with, and i am not sure list way will provide much performance gain :)
Sarfraz
+1  A: 

$sortA == $sortB so that part is just duplication. Calculate $sortA once wherever you set $this->sortBy. The Arr::get lines you're stuck with. The return $a < $b; seems wrong, you should be returning a -ve, 0, +ve number.

...
function setSortBy($sortBy) {
    $this->sortBy = $sortBy;
    $this->sortByCam = inflector::camelize(str_replace('-', '_', $sortBy));
}
....

public function sortProperties($a, $b) {

    $a = Arr::get($a, $this->sortByCam);
    $b = Arr::get($b, $this->sortByCam);

    if (is_numeric($a) && is_numeric($b)) {
        return $a - $b;
    } else {
        return strcasecmp($a, $b); 
    }

}

Something like that. The main idea to get the camelizing part out of the loop.

Mike
The return `return $a < $b;` does work how I intended it to. I guess positive number = true or negative number = false
alex
`true` gets cast to `1`, `false` gets cast to `0` and your sort is lobotomised because the function can't indicate numeric `$a` is greater than `$b`. It also doesn't match the same sense as your strcasecmp which will return -1 if `$a < $b`. If it's working and you're happy with it then it doesn't matter, but it isn't right.
Mike
A: 

“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson

There is also another rule that says don't fix what is not broken. Think about it; it's just one line of code, the time you spent posting this question, reading the answer and all the comments could have been used to write a large chunk of code for a different task in your project.

e4c5
Generally, you'd be correct, but I knocked off work after posting this and am reading it in my own time. Still, I'm only trying to optimise readability and best practice, not performance.
alex
Your advice only applies to performance optimization.
Ollie Saunders
On the contrary any optimization be it performance or otherwise is a violation of the don't fix it if it is not broken rule. Remember, you need to spend a lot of time testing the new code. The only benefit is to reduce the length of your code by 1 line.
e4c5
A: 

Be aware that strcasecmp will return an int (1, 0, or -1) and < will return a boolean. You really need to be using one or the other. Also note that strnatcasecmp will probably give you the behavior you want for both numbers and strings so try this one:

public function sortProperties($a, $b) {
  $aInflected = Arr::get($a, $sort = inflector::camelize(str_replace('-', '_', $this->sortBy)));
  return strcasecmp($aInflected, Arr::get($b, $sort));
}
Ollie Saunders
Thanks, that did indeed work and was less verbose. +1
alex