Order Array in groups

Viewed 51

i have an array like this with position disordered i want to order the position like 123 123 123 12

[{
    "id": 1,
    "name": "ASDAS",
    "position": 1,
   },
   {
    "id": 2,
    "name": "ASDAS",
    "position": 1,
   },
   {
    "id": 3,
    "name": "ASDAS",
    "position": 3,
   },
  {
    "id": 4,
    "name": "ASDAS",
    "position": 2,
   },
  {
    "id": 5,
    "name": "ASDAS",
    "position": 2,
   },
   {
    "id": 6,
    "name": "ASDAS",
    "position": 3,
   },
  {
    "id": 7,
    "name": "ASDAS",
    "position": 2,
   },
  {
    "id": 8,
    "name": "ASDAS",
    "position": 1,
   }
  ]

i want the order like that

 [{
    "id": 1,
    "name": "ASDAS",
    "position": 1,
   },
{
    "id": 4,
    "name": "ASDAS",
    "position": 2,
   },
   {
    "id": 3,
    "name": "ASDAS",
    "position": 3,
   },
  {
    "id": 2,
    "name": "ASDAS",
    "position": 1,
   },
  {
    "id": 5,
    "name": "ASDAS",
    "position": 2,
   },
   {
    "id": 6,
    "name": "ASDAS",
    "position": 3,
   },
  {
    "id": 8,
    "name": "ASDAS",
    "position": 1,
   },
  {
    "id": 7,
    "name": "ASDAS",
    "position": 2,
   }
  ]
2 Answers

The below should do the trick. I assume your data is an array of objects.

First I order the array by ID and then seperate the items by group. Finally, I merge all the groups 1 item at a time. There is probably a better way to acheive what you are after but thought this might be a good starting point.

This will adapt to the max position value. For example, if one of the data items has a position of 4 you would end up with a position order: 1234 123 123 123 12... etc

<?php

$input = [
    (object)[
        "id" => 1,
        "name" => "ASDAS",
        "position" => 1,
    ],
    (object)[
        "id" => 2,
        "name" => "ASDAS",
        "position" => 1,
    ],
    (object)[
        "id" => 3,
        "name" => "ASDAS",
        "position" => 3,
    ],
    (object)[
        "id" => 4,
        "name" => "ASDAS",
        "position" => 2,
    ],
    (object)[
        "id" => 5,
        "name" => "ASDAS",
        "position" => 2,
    ],
    (object)[
        "id" => 6,
        "name" => "ASDAS",
        "position" => 3,
    ],
    (object)[
        "id" => 7,
        "name" => "ASDAS",
        "position" => 2,
    ],
    (object)[
        "id" => 8,
        "name" => "ASDAS",
        "position" => 1,
    ]
];


// Sort array by ID
usort($input, function($a, $b) {
    return $a->id <=> $b->id;
});

$groups = [];

foreach ($input as $item) {

    // Create new group array
    if (!array_key_exists($item->position, $groups)) {
        $groups[$item->position] = [];
    }

    // Add item to group
    $groups[$item->position][] = $item;
}

// Sort groups by position
ksort($groups);

// Merge groups 1 item at a time
function merge_groups(&$groups, &$target) {
    foreach ($groups as $position => $group) {
        if (!empty($group)) {
            $target[] = array_shift($groups[$position]);
        } else {
            unset($groups[$position]);
        }
    }

    if (!empty($groups)) {
        merge_groups($groups, $target);
    }
}

// Our final result array
$ouput = [];

merge_groups($groups, $ouput);

var_dump($ouput);

Tested in PHP 7.

Solution with simple loops. Foreach searches for a specific position and then increases the position. The number of positions can be more than 3. Positions like 123 123 23 are also possible.

$input = [
    (object)[
        "id" => 1,
        "name" => "ASDAS",
        "position" => 1,
    ],
    (object)[
        "id" => 2,
        "name" => "ASDAS",
        "position" => 1,
    ],
    (object)[
        "id" => 3,
        "name" => "ASDAS",
        "position" => 3,
    ],
    (object)[
        "id" => 4,
        "name" => "ASDAS",
        "position" => 2,
    ],
    (object)[
        "id" => 5,
        "name" => "ASDAS",
        "position" => 2,
    ],
    (object)[
        "id" => 6,
        "name" => "ASDAS",
        "position" => 3,
    ],
    (object)[
        "id" => 7,
        "name" => "ASDAS",
        "position" => 2,
    ],
    (object)[
        "id" => 8,
        "name" => "ASDAS",
        "position" => 1,
    ]
];

$minPos = min(array_column($input, "position"));
$arr = [];
$pos = $minPos;

while(true){
  $found = false;
  foreach($input as $key => $obj){
    if($obj->position == $pos){
      $arr[] = $obj;
      unset($input[$key]);
      ++$pos;
      $found = true;
    }
  }
  if(empty($input)) break;
  $minPos = min(array_column($input, "position"));
  if(!$found AND $pos != $minPos){
    $pos = $minPos;
  }
}
var_dump($arr);
Related