1

I am trying to sort json object by same key and merge the value part using PHP but not getting the result as expected. My code is below:

$customArr=[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]
function sortByName($a, $b){
    $a = $a['attribute_code'];
    $b = $b['attribute_code'];

    if ($a == $b) return 0;
    return ($a < $b) ? -1 : 1;
}
usort($customArr, 'sortByName');

Here I need if attribute_code is same then push the respective value into one array and also the duplicate value should not be there. The expected result is given below.

[{"attribute_code":"budget","value":[141,142,143,162]},{}.....]

But in my case the expected result not coming.

4
  • JSON is JavaScript Object Notation which is not PHP. Commented Jul 25, 2019 at 6:37
  • @GentleSama: That is` json_encode` output. Commented Jul 25, 2019 at 6:39
  • What is output of json_encode? Your $customArr? Commented Jul 25, 2019 at 6:42
  • @GentleSama: Yes. Commented Jul 25, 2019 at 6:42

4 Answers 4

2

Using array_reduce() you can try it. array_reduce() callback takes two arguments, who's first argument is the old/previous iteration value and second argument is the current iteration value/element.

So using this function we can holds our current iteration values to the previous iteration value (total values).

array_reduce() iteratively reduce the array to a single value using a callback function.

$customArr = json_decode('[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]', true);

$data = array_reduce($customArr, function ($acc, $new) {
    if (isset($acc[$new['attribute_code']])) {
        $old_value = $acc[$new['attribute_code']]['value'];
        $acc[$new['attribute_code']]['value'] = array_unique(is_array($old_value) ? array_merge($old_value, [$new['value']]) : [$old_value, $new['value']]);
    } else {
        $acc[$new['attribute_code']] = $new;
    }
    return $acc;
}, []);

ksort($data);

echo '<pre>', json_encode(array_values($data));

Working demo.

Sign up to request clarification or add additional context in comments.

Comments

1

At the moment you are just sorting the entries according to the attribute_code and doing nothing about merging the data items.

This code creates a new output array (keyed it by the attribute_code), if the code is already there it adds the value into the list of existing values, if not it adds a new item in, creating the value as an array (with the first item in). Lastly it uses ksort() to sort the items.

If you don't need these keys, then array_values() will give you a plain array (as in the output)...

$json='[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';

$customArr = json_decode($json, true);
$output = [];
foreach ( $customArr as $attribute )    {
    if ( isset ( $output[$attribute['attribute_code']]))    {
        $output[$attribute['attribute_code']]['value'][] = $attribute['value'];
    }
    else    {
        $output[$attribute['attribute_code']] = ["attribute_code"=>$attribute['attribute_code'],
            "value"=> [$attribute['value']]];
    }
}
// Make sure values are unique
foreach ( $output as $code => $value ){
    $output[$code]['value'] = array_unique($output[$code]['value']);
}
ksort($output);
print_r(array_values($output));

gives...

Array
(
    [0] => Array
        (
            [attribute_code] => budget
            [value] => Array
                (
                    [0] => 141
                    [1] => 142
                    [2] => 143
                    [3] => 162
                )

        )

    [1] => Array
        (
            [attribute_code] => food_type
            [value] => Array
                (
                    [0] => 172
                    [1] => 173
                )

        )

    [2] => Array
        (
            [attribute_code] => restaurants
            [value] => Array
                (
                    [0] => 166
                    [1] => 168
                    [2] => 170
                    [3] => 171
                )

        )

)

3 Comments

Yes it looks fine but still duplicate value is there.
I've added a loop at the end so that the values are also unique (saves calling array_unique() every time)
We can remove one loop and can use a temp variable to get a similar result.
0

You have a JSON string, not an array.

$jsonString = '[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$customArr = json_decode($jsonString, true);

    function sortByName($a, $b)
    {
        $a = $a['attribute_code'];
        $b = $b['attribute_code'];

        if ($a == $b) return 0;
        return ($a < $b) ? -1 : 1;
    }

    usort($customArr, 'sortByName');

1 Comment

Is this the solutions ?
0

The similar solution as above, but a little different using a temp variable and in a single iteration:

<?php 
$str='[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$arr = json_decode($str,true);
$temp = $result= [];
foreach($arr as $key=>$customer){
    if(in_array($customer['attribute_code'], $temp)){
        $index=array_search($customer['attribute_code'],$temp);
        if(!in_array($customer['value'],$result[$index]['value'])){
            $result[$index]['value'][]=$customer['value'];
        }
    }else {
        $temp[]=$customer['attribute_code'];
        $result[]=[
            'attribute_code'=>$customer['attribute_code'],
            'value'=>[$customer['value']]
        ];
    }
}
unset($temp);
print_r($result);
echo json_encode($result);
?>

Result :

Array
(
[0] => Array
    (
        [attribute_code] => budget
        [value] => Array
            (
                [0] => 141
                [1] => 142
                [2] => 143
                [3] => 162
            )

    )

[1] => Array
    (
        [attribute_code] => restaurants
        [value] => Array
            (
                [0] => 166
                [1] => 168
                [2] => 170
                [3] => 171
            )

    )

[2] => Array
    (
        [attribute_code] => food_type
        [value] => Array
            (
                [0] => 172
                [1] => 173
            )

    )

)

JSON ENCODED RESPONSE

  [{"attribute_code":"budget","value":["141","142","143","162"]},{"attribute_code":"restaurants","value":["166","168","170","171"]},{"attribute_code":"food_type","value":["172","173"]}]

Comments

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.