1

I have one array with objects, and what I would like to achieve is to group the objects if a similar key already exists. What my JSON output looks like is,

[
  {
    "id": 37,
    "slug": "red",        
    "stock": true,
    "name": "Red",
    "default": 0,
    "sizes": "38"
  },
  {
    "id": 38,
    "slug": "red",        
    "stock": true,
    "name": "Red",
    "default": 0,
    "sizes": "40"
  },
  {
    "id": 34,
    "slug": "red",        
    "stock": true,
    "name": "Red",
    "default": 0,
    "sizes": "36"
  },
  {
    "id": 26,
    "slug": "green",
    "stock": true,
    "name": "Green",
    "default": 0,
    "sizes": "48"
  }

What I would like to achieve is to group the similar slugs, and have an array of all the sizes in one. So something like this below,

[
{
  "slug": "red",
  "name": "Red",
  "sizes" : [{
      "id": 37,
      "slug": "red",        
      "stock": true,
      "name": "Red",
      "default": 0,
      "sizes": "38"
    },
    {
      "id": 38,
      "slug": "red",        
      "stock": true,
      "name": "Red",
      "default": 0,
      "sizes": "40"
    },
    {
      "id": 34,
      "slug": "red",        
      "stock": true,
      "name": "Red",
      "default": 0,
      "sizes": "36"
    }]
}, {
  "slug": "green",
  "name": "Green",
  "sizes": [{
    "id": 26,
    "slug": "green",
    "stock": true,
    "name": "Green",
    "default": 0,
    "sizes": "48"
  }]
}

]

I'm not so much of a PHP guru, so been trying to figure out all day how to do this searching all over, and hoping someone fluent in PHP can help me out.

anon
  • 594
  • 6
  • 25

2 Answers2

3

You can use one loop to group your result by slug first and then use another to get what you want. Let's try like this way-

<?php
$json = '[{"id":37,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"38"},{"id":38,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"40"},{"id":34,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"36"},{"id":26,"slug":"green","stock":true,"name":"Green","default":0,"sizes":"48"}]';
$array = json_decode($json,1);

$expected = [];
foreach($array as $v) {
    $expected[$v['slug']][] = $v;
}

$expected_v2 = [];
foreach($expected as $k1=>$v1) {
    array_push($expected_v2,['slug'=>$k1,'name'=>ucfirst($k1),'sizes'=>$v1]);
}

//print_r($expected_v2);
echo json_encode($expected_v2);
?>

Output:

[{"slug":"red","name":"Red","sizes":[{"id":37,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"38"},{"id":38,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"40"},{"id":34,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"36"}]},{"slug":"green","name":"Green","sizes":[{"id":26,"slug":"green","stock":true,"name":"Green","default":0,"sizes":"48"}]}]

DEMO: https://3v4l.org/WfbsX

A l w a y s S u n n y
  • 36,497
  • 8
  • 60
  • 103
1

You can use `array_reduce to achieve this :

$json = '[{"id":37,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"38"},{"id":38,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"40"},{"id":34,"slug":"red","stock":true,"name":"Red","default":0,"sizes":"36"},{"id":26,"slug":"green","stock":true,"name":"Green","default":0,"sizes":"48"}]';
$input = json_decode($json, true);

$output = array_reduce(array_reduce($input, function ($carry, $item) {
    $carry[$item['slug']][] = $item;
    return $carry;
}, []), function ($carry, $group) {
    $carry[] = [
        'slug' => $group[0]['slug'],
        'name' => $group[0]['name'],
        'sizes' => $group
    ];
    return $carry;
}, []);
mrbm
  • 2,164
  • 12
  • 11