Array reduce with associative array

4.4k Views Asked by At

I have an array like this

 $filter_array = Array
    (
        [0] => Array
            (
                [fv_id] => 1
                [fv_value] => Red
                [filter_id] => 1
                [filter_name] => Color
            )

        [1] => Array
            (
                [fv_id] => 2
                [fv_value] => Blue
                [filter_id] => 1
                [filter_name] => Color
            )

    )

I would like to reduce the array by having filter_name and filter_id on top of array which is similar for all arrays.

$newArray = array_reduce($filter_array,function($carry,$item){

            $allFilterValues[] = array(
                'fv_id' => $item['fv_id'],
                'fv_value' => $item['fv_value'],
            );

             $formated_array = array(
                'filter_id' => $item['filter_id'],
                'filter_name' => $item['filter_name'],
                'filter_values' => $allFilterValues
            );
            return $formated_array;
        });

But I am just getting the last array iterations value on filter_values

Array
(
    [filter_id] => 1
    [filter_name] => Color
    [filter_values] => Array
        (
            [0] => Array
                (
                    [fv_id] => 2
                    [fv_value] => Blue
                )

        )

)

But I want the array be like this.

Array
(
    [filter_id] => 1
    [filter_name] => Color
    [filter_values] => Array
        (
                [0] => Array
                (
                    [fv_id] => 1
                    [fv_value] => Red
                ),

                [1] => Array
                (
                    [fv_id] => 2
                    [fv_value] => Blue
                )

        )

)
1

There are 1 best solutions below

4
On BEST ANSWER

On each iteration of array_reduce callback function must return current $carry value:

$newArray = array_reduce($filter_array,function($carry,$item){
    // create key so as to distinct values from each other
    $key = $item['filter_id'] . '-' . $item['filter_name'];

    // check if created key exists in `$carry`, 
    // if not - we init it with some data
    if (empty($carry[$key])) {
        $carry[$key] = [
            'filter_id' => $item['filter_id'],
            'filter_name' => $item['filter_name'],
            'filter_values' => []
        ];
    }

    // add values to `filter_values`
    $carry[$key]['filter_values'][] = [
        'fv_id' => $item['fv_id'],
        'fv_value' => $item['fv_value'],
    ];

    return $carry;
}, []);

// if you want to reindex `$newArray` from 0:
$newArray = array_values($newArray);

Update: if and only if in your $filter_array values of 'filter_id' and 'filter_name' are always the same you can simplify your code:

$newArray = [];
$first = true;
foreach ($filter_array as $item) {
    if ($first) {
        $first = false;
        $newArray = [
            'filter_id' => $item['filter_id'],
            'filter_value' => $item['filter_name'],
            'filter_values' => []
        ];
    }

    $newArray['filter_values'][] = [
        'fv_id' => $item['fv_id'],
        'fv_value' => $item['fv_value'],
    ];
}
echo'<pre>',print_r($newArray),'</pre>';