0

I have this this JSON.

{
    "animals": [{
        "name": "Cumi-Cumi",
        "data": 1000
    }, {
        "name": "Udang",
        "data": 300
    }, {
        "name": "Baranang",
        "data": 12000
    }, {
        "name": "Cumi-Cumi",
        "data": 1500
    }, {
        "name": "Udang",
        "data": 500
    }, {
        "name": "Baranang",
        "data": 17000
    }, {
        "name": "Cumi-Cumi",
        "data": 2500
    }]
}

How can I group the data key by its name, to be like this:

{
    "animals": [{
            "name": "Cumi-Cumi",
            "data": [
                1000, 1500, 2500
            ]
        },
        {
            "name": "udang",
            "data": [
                300, 500
            ]
        },
        {
            "name": "Baranang",
            "data": [
                12000, 17000
            ]
        }
    ]
}

2 Answers 2

1

It might be because I'm tired, but I can't figure out how to make this more concise...
This is a start for you anyway.

$json = '{
    "animals": [{
        "name": "Cumi-Cumi",
        "data": 1000
    }, {
        "name": "Udang",
        "data": 300
    }, {
        "name": "Baranang",
        "data": 12000
    }, {
        "name": "Cumi-Cumi",
        "data": 1500
    }, {
        "name": "Udang",
        "data": 500
    }, {
        "name": "Baranang",
        "data": 17000
    }, {
        "name": "Cumi-Cumi",
        "data": 2500
    }]
}';

// Start by decoding the JSON (I assume it comes as a string, if not, then ignore this).
$collection = collect(json_decode($json, true))
// Now iterate over the keys (you only have one key (animals), but I wanted to be safe).
->map(function ($item) {
    // Convert the sub arrays into a Collection, then group the data against each animal name.
    // Then map (iterate) over each of the animals, one at a time.
    return collect($item)->groupBy('name')->map(function ($animal) {
        // Reduce each animal into a single entry.
        return $animal->reduce(function ($carry, $data) {
            // Use the name of the animal, then push the data onto the end. Feel free to sort at this point too!
            $carry['name'] = $data['name'];
            $carry['data'][] = $data['data'];
            return $carry;
        });
    // Finally, I reset the groupBy keys to ensure it matches your desired output.
    })->values();
});
Sign up to request clarification or add additional context in comments.

Comments

1

JustCarty's solution is probably better, but I wanted to post mine anyways.

// get json string
$json = <<<JSON
{
    "animals": [{
        "name": "Cumi-Cumi",
        "data": 1000
    }, {
        "name": "Udang",
        "data": 300
    }, {
        "name": "Baranang",
        "data": 12000
    }, {
        "name": "Cumi-Cumi",
        "data": 1500
    }, {
        "name": "Udang",
        "data": 500
    }, {
        "name": "Baranang",
        "data": 17000
    }, {
        "name": "Cumi-Cumi",
        "data": 2500
    }]
}
JSON;
$result = collect(json_decode($json, true)) // transform $json into a collection
    ->map(function ($item) { // map over it
        return collect($item); // make the animals array a collection
    })
    ->map(function ($animals) { // map over it
        return $animals
            ->unique('name') // leave only uniquely named animals
            ->map(function ($item) use ($animals) { // map over them
                return [
                    'name' => $item['name'],
                    'data' => $animals->where('name', $item['name'])->pluck('data')->all()
                ]; // replace their 'data' values by the array of 'data' from each unique animal.
            });
    })
    ->toJson(); // turn back to json string

Using PHP 7.4 shorthand closures:

$results = collect(json_decode($json, true))
    ->map(fn($item) => collect($item))
    ->map(fn($item) => $item->unique('name')->map(fn($animal) => [
        'name' => $animal['name'],
        'data' => $item->where('name', $animal['name'])->pluck('data')->all()
    ]))
    ->toJson();

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.