getupkid203's avatar

Sort collection keys by custom order

Hello.

I'm trying to sort a collection by a custom order using the keys of the collection once it's grouped.

Take this collection for example:

$staff = collect([
 [ "name" => "John", "role" => "Producer" ],
 [ "name" => "Phoebe", "role" => "Editor" ],
 [ "name" => "Joanne", "role" => "Producer" ],
 [ "name" => "Kevin", "role" => "Director" ],
 [ "name" => "Christine", "role" => "Director" ],
]);

Firstly, I want to group them by role, which is easy enough using groupBy():

$staff = collect([
 [ "name" => "John", "role" => "Producer" ],
 [ "name" => "Phoebe", "role" => "Editor" ],
 [ "name" => "Joanne", "role" => "Producer" ],
 [ "name" => "Kevin", "role" => "Director" ],
 [ "name" => "Christine", "role" => "Director" ],
])
->groupBy("role");

which will give me:

array:3 [▼
  "Producer" => array:2 [▼
    0 => array:2 [▼
      "name" => "John"
      "role" => "Producer"
    ]
    1 => array:2 [▼
      "name" => "Joanne"
      "role" => "Producer"
    ]
  ]
  "Editor" => array:1 [▼
    0 => array:2 [▼
      "name" => "Phoebe"
      "role" => "Editor"
    ]
  ]
  "Director" => array:2 [▼
    0 => array:2 [▼
      "name" => "Kevin"
      "role" => "Director"
    ]
    1 => array:2 [▼
      "name" => "Christine"
      "role" => "Director"
    ]
  ]
]

but then I want to be able to pass a custom order (most likely using an array) so I can sort the collection using this custom order, for example:

$order = ["Editor", "Director", "Producer"];

so I can achieve:

[
	"Editor" => [
		// Array of editors
	],
	"Director" => [
		// Array of directors
	],
	"Producer" => [
	     // Array of producers
	]
]

I can achieve this using a couple of foreach loops, but I'm just wondering how to achieve this using sortBy() or sort(). I've tried using both and passing through a callback but it always returns an error.

Any help is appreciated.

Cheers.

0 likes
5 replies
MichalOravec's avatar

It could be it like this

$order = ["Editor", "Director", "Producer"];

$staff = collect([
    ["name" => "John", "role" => "Producer"],
    ["name" => "Phoebe", "role" => "Editor"],
    ["name" => "Joanne", "role" => "Producer"],
    ["name" => "Kevin", "role" => "Director"],
    ["name" => "Christine", "role" => "Director"],
])->sortBy(function($item) use ($order) {
    return array_search($item["role"], $order);
})->groupBy("role");
1 like
getupkid203's avatar
getupkid203
OP
Best Answer
Level 6

Nevermind! I figured it out already. Found the solutions here https://stackoverflow.com/questions/40731863/sort-collection-by-custom-order-in-eloquent

To anyone else who is interested:

$order = ["Editor", "Director", "Producer"];
$staff = collect([
    [ "name" => "John", "role" => "Producer" ],
    [ "name" => "Phoebe", "role" => "Editor" ],
    [ "name" => "Joanne", "role" => "Producer" ],
    [ "name" => "Kevin", "role" => "Director" ],
    [ "name" => "Christine", "role" => "Director" ],
])
->groupBy("role")
->sortBy( function($item, $key) use ($order) {
    return array_search($key, $order);
});

produces:

Illuminate\Support\Collection {#1601 ▼
  #items: array:3 [▼
    "Editor" => Illuminate\Support\Collection {#1546 ▶}
    "Director" => Illuminate\Support\Collection {#1784 ▶}
    "Producer" => Illuminate\Support\Collection {#1861 ▶}
  ]
}
1 like
getupkid203's avatar

hahaha yep I just found it haha thanks for the reply though I appreciate it.

tykus's avatar

There is no guarantee that groupBy will not affect the sorting in the previous step @michaloravec

Please or to participate in this conversation.