HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Generic array group by using lambda

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
genericgrouparrayusinglambda

Problem

This is K.I.S.S, but how about some error and misuse control? I am wishing it were .NET.

Solution


  • Using the [] syntax for adding array items, allows PHP to create the array as necessary. Thus you can scrap the if statement for a modest performance increase off 10 to 15% in my own testing. (Unlike if you used array_push() which would throw a warning instead.



-
The unused $group variable appears to be a mistake, as the function appears to fulfill it's purpose without it. Code reduced to:

function array_group_by($arr, $key_selector) {
  $result = array();
  foreach ($arr as $i) {
    $key = $key_selector($i);
    $result[$key][] = $i;
  }
  return $result;
}


  • At this point, the $key could also be left out, but it's almost free in terms of performance, and increases readability, so I left it there.



-
I'm not sure how much misuse and error handling you need, the function is pretty simple. I would stick with type-hinting the arguments. array is available since PHP 5.1, callable since 5.4. The signature would become

function array_group_by(array $arr, callable $key_selector);


Then PHP will at run-time throw a fatal error at anyone trying to call the function with incorrect parameters. Generally I think that's good, but in this particular case, it introduces a problem.
array('class_A', 'method_B'), is a valid callable, that won't work with with the fast $function($arg);. For any valid callable to get executed, you need to use call_user_func() instead, which is a bit slower. In my testing however, the removal of the if has bigger impact than the use of call_user_func(), so if this isn't performance critical, stick with callable and call_user_func().

Final code:

function array_group_by(array $arr, callable $key_selector) {
  $result = array();
  foreach ($arr as $i) {
    $key = call_user_func($key_selector, $i);
    $result[$key][] = $i;
  }  
  return $result;
}

Code Snippets

function array_group_by($arr, $key_selector) {
  $result = array();
  foreach ($arr as $i) {
    $key = $key_selector($i);
    $result[$key][] = $i;
  }
  return $result;
}
function array_group_by(array $arr, callable $key_selector);
function array_group_by(array $arr, callable $key_selector) {
  $result = array();
  foreach ($arr as $i) {
    $key = call_user_func($key_selector, $i);
    $result[$key][] = $i;
  }  
  return $result;
}

Context

StackExchange Code Review Q#23919, answer score: 4

Revisions (0)

No revisions yet.