Skip to content

Instantly share code, notes, and snippets.

@tnorthcutt
Last active January 29, 2018 14:32
Show Gist options
  • Select an option

  • Save tnorthcutt/385626e2d193479436e2a84d92263de2 to your computer and use it in GitHub Desktop.

Select an option

Save tnorthcutt/385626e2d193479436e2a84d92263de2 to your computer and use it in GitHub Desktop.
Given this collection:
Illuminate\Support\Collection {#1108
all: [
"verb" => [
"have",
"have-not",
],
"type" => [
"1",
"2",
],
"days" => [
"30",
"10",
],
],
}
How can I change it to:
Illuminate\Support\Collection {#1121
all: [
[
"verb" => [
"have",
],
"type" => [
"1",
],
"days" => [
"30",
],
],
[
"verb" => [
"have-not",
],
"type" => [
"2",
],
"days" => [
"10",
],
],
],
}
@adamwathan
Copy link

The transpose operation can help here, although it's not built-in to Laravel due to a bunch of bike-shedding over edge case behavior :)

Here's a quick implementation:

Collection::macro('transpose', function () {
    $items = array_map(function (...$items) {
        return $items;
    }, ...$this->values());

    return new static($items);
});

...and here's a blog post that explains what it does:

https://adamwathan.me/2016/04/06/cleaning-up-form-input-with-transpose/

Using that + an extra map operation, you can get your desired output like so:

$input = collect([
    "verb" => [
        "have",
        "have-not",
    ],
    "type" => [
        "1",
        "2",
    ],
    "days" => [
        "30",
        "10",
    ]
]);

return $input->transpose()->map(function ($items) use ($input) {
    return $input->keys()->combine($items);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment