skip to Main Content

Supposing I have this array in PHP:

Array
(
    [0] => Array
        (
            [color] => Yellow
            [name] => Banana
            [quantity] => 124
        )
    [1] => Array
        (
            [color] => Red
            [name] => Cherry
            [quantity] => 24
        )
    [2] => Array
        (
            [color] => Yellow
            [name] => Apple
            [quantity] => 224
        )

)

How can I reduce this array if :

  • color is yellow and
  • quantity is the lowest

So from the example above, I should have only this array:

Array
(
    [0] => Array
        (
            [color] => Yellow
            [name] => Banana
            [quantity] => 124
        )    
)

What I have tried so far:

$min = array_reduce($array, function($min, $details) {
  return min($min, $details['quantity']);
}, PHP_INT_MAX);

Thanks for any help.

3

Answers


  1. I would just use a simple loop like this, because it’s readable and easy to understand what is happening.

    foreach($array as $arr) {
        if($arr['color'] == 'Yellow') {
            if(!isset($min) || $min['quantity'] > $arr['quantity']) {
                $min = $arr;
            }   
        }
    }
    
    print_r($min);
    

    Output

    Array
    (
        [color] => Yellow
        [name] => Banana
        [quantity] => 124
    )
    

    If you want $min to still be an array like your example output, you can just add it to an array like this.

    if(isset($min)) $min = [$min];
    

    Output

    Array
    (
        [0] => Array
            (
                [color] => Yellow
                [name] => Banana
                [quantity] => 124
            )
    
    )
    
    Login or Signup to reply.
  2. A possible solution.

    This solution takes into consideration what has already been created by the applicant, completing the code to obtain the required result.

    $filtered = array_filter ($array, fn ($v) =>  $v['color'] == 'Yellow');
    $min = array_reduce($filtered, fn ($minVal, $v) => min($minVal, $v['quantity']), PHP_INT_MAX);
    $filtered = array_filter ($filtered, fn ($v) => $v['quantity'] == $min);
    
    print_r ($filtered);
    

    The first array_filter selects all rows that have color = ‘Yellow’, decreasing the dataset to process.

    With array_reduce we find the smallest value of quantity, like @F_M did, but on a smaller dataset.

    Finally with another array_filter we are going to extract the row with the value just found.

    Login or Signup to reply.
  3. I tried to make a more versatile, generic function that could be modified to suit other similar scenarios where the input array does not necessarily contain the keys/values cited in the question.

    $src=array(
        array(
            'colour'=>'Red',
            'name'=>'raspberry',
            'qty'=>524
        ),
        array(
            'colour'=>'yellow',
            'name'=>'Banana',
            'qty'=>124
        ),
        array(
            'colour'=>'green',
            'name'=>'gooseberry',
            'qty'=>23
        ),
        array(
            'colour'=>'Red',
            'name'=>'Cherry',
            'qty'=>24
        ),
        array(
            'colour'=>'green',
            'name'=>'cucumber',
            'qty'=>457
        ),
        array(
            'colour'=>'yellow',
            'name'=>'Banana',
            'qty'=>225
        ),
        array(
            'colour'=>'purple',
            'name'=>'Plum',
            'qty'=>40
        ),
        array(
            'colour'=>'Red',
            'name'=>'strawberry',
            'qty'=>1245
        ),
        array(
            'colour'=>'green',
            'name'=>'lime',
            'qty'=>44520
        ),
        array(
            'colour'=>'yellow',
            'name'=>'mango',
            'qty'=>6225
        )
    );
    
    # criteria to apply to the filter
    $key='colour';
    $value='yellow';
    $column='qty';
    $dir='low';
    
    
    
    function filter( $input, $key, $value, $column, $dir='low' ){
        # filter the array by matching desired field to desired value, ignoring case.
        $filtered=array_filter( $input, function( $item ) use( $key, $value ){
            return is_array( $item ) && strtolower( $item[ $key ] )==strtolower( $value );
        });
        
        # determine the sort order for the filtered results.
        $sort=$dir=='low' ? SORT_ASC : SORT_DESC;
        
        # find the columns by which final output is derived.
        $cols=array_column( $filtered, $column );
        
        # sort the columns.
        array_multisort( $cols, $sort, $filtered );
        
        # return the first item from filtered & now sorted data.
        return array_shift( $filtered );
    }
    
    # run the filter
    $result=filter( $src, $key, $value, $column, $dir );
    
    
    printf(
        '<pre>%s</pre>', 
        print_r( is_null( $result ) ? 'No results' : $result, true )
    );
    

    The above yields:

    Array
    (
        [colour] => yellow
        [name] => Banana
        [qty] => 124
    )
    

    If the criteria change and you need the highest rather than lowest that can be quickly realised by modifying the $dir variable.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search