1

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
                )

        )

)
2
  • If you are merging on filter_id why do you abandon it as an array key? Are you sure you have the key names as they should be? It seems to me you should be using filter_id and filter_name as keys before each subgroup. Commented Jul 16, 2017 at 8:02
  • 1
    On each iteration of array_reduce callback you should return $carry Commented Jul 16, 2017 at 8:04

1 Answer 1

3

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>';
Sign up to request clarification or add additional context in comments.

4 Comments

Is any other array function makes things easier than this?
I suppose no. But you can rewrite this as a foreach.
Can you please tell me why you have passed [] after the callback argument in array_reduce?
Created a little update for code simplifying. As for your question - I pass [] as initial value of $carry. Of course, php can decide what initial value of $carry you use, so it's just my personal approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.