Morgan
Morgan

Reputation: 584

PHP array_filter on array containing multiple arrays

I'm using array_filter in PHP to split an array containing multiple arrays when the value of a key named type matches a specific string. Here's what this looks like:

Sample Array

$arr[] = Array (
    [0] => Array ( [type] => Recurring ... )
    [1] => Array ( [type] => Single ... )
)

Functions

function recurring($value)
{
    return ($value['type'] == 'Recurring');
}

function single($value)
{
    return ($value['type'] == 'Single');
}

Split Arrays

$recurring = array_filter($arr, 'recurring');
$single    = array_filter($arr, 'single');

This works, but I was curious if there was a way to simplify it so that I could create additional filtered arrays in the future without creating a new function for each.

I've started setting up a single function using a closure, but I'm not sure how to do it. Any ideas?

function key_type($value, $key, $string) {
    return $key == 'type' && $value == $string;
}

$recurring = array_filter($arr, 
key_type('Recurring'), ARRAY_FILTER_USE_BOTH);

$single = array_filter($pricing, 
key_type('Single'), ARRAY_FILTER_USE_BOTH);

Upvotes: 3

Views: 2599

Answers (3)

mickmackusa
mickmackusa

Reputation: 48073

This task might be more about grouping than filtering -- it is difficult to discern from the limited sample data.

As a general rule, I strongly advise against using variable variables in PHP code. It is better practice to store data in arrays for accessibility reasons.

If you only have the two mentioned type values in your project data, then the conditional can be removed entirely.

Code: (Demo)

$array = [
    ['type' => 'Recurring', 'id' => 1],
    ['type' => 'Single',    'id' => 2],
    ['type' => 'Other',     'id' => 3],
    ['type' => 'Recurring', 'id' => 4],
    ['type' => 'Single',    'id' => 5],
];

$result = [];
foreach ($array as $row) {
    if (in_array($row['type'], ['Recurring', 'Single'])) {
        $result[strtolower($row['type'])][] = $row;
    }
}
var_export($result);

Output:

array (
  'recurring' => 
  array (
    0 => 
    array (
      'type' => 'Recurring',
      'id' => 1,
    ),
    1 => 
    array (
      'type' => 'Recurring',
      'id' => 4,
    ),
  ),
  'single' => 
  array (
    0 => 
    array (
      'type' => 'Single',
      'id' => 2,
    ),
    1 => 
    array (
      'type' => 'Single',
      'id' => 5,
    ),
  ),
)

Upvotes: 0

Cave Johnson
Cave Johnson

Reputation: 6788

You could actually do what you proposed in your question. You just need to have the key_type() function return a callable function, which is what array_filter expects as the second parameter. You can return an anonymous function and pass the argument into the anonymous function using the use keyword as CBroe mentioned in the comments.

Here is an example:

function key_type($key) {
    return function($value) use ($key) {
        return $value['type'] == $key;
    };
}

$arr = array(
    array('type'=>'Recurring'),
    array('type'=>'Single')
);
print_r(array_filter($arr, key_type('Single'), ARRAY_FILTER_USE_BOTH));

The above code will output:

Array ( [1] => Array ( [type] => Single ) )

The beauty of this method is that if you need to change the logic for all instances where you need to use your filter, you just have to change it one time in your key_type function.

Upvotes: 2

revo
revo

Reputation: 48751

An approach would be like below, however I don't like it honestly.

$array = [['type' => 'Single'], ['type' => 'Recurring']];

function key_type($value) {
    global $string;
    return $value['type'] == $string;
}

($string = 'Recurring') && ($recurring = array_filter($array, 'key_type'));

($string = 'Single') && ($single = array_filter($array, 'key_type'));

Another way to achieve same thing is using Anonymous functions (closures). Don't think much about being DRY it seems nice:

$array = [['type' => 'Single'], ['type' => 'Recurring']];

$recurring = array_filter($array, function($value) {
    return $value['type'] == 'Recurring';
});

$single = array_filter($array, function($value) {
    return $value['type'] == 'Single';
});

Upvotes: 2

Related Questions