Group and flip Laravel collection to create delimited keys for each grouping valuevalue

How can a group a collection based on their values? For example this one:

Collection {#250 ▼
  #items: array:4 [▼
    "CASSETE_1" => "500"
    "CASSETE_2" => "500"
    "CASSETE_3" => "100"
    "CASSETE_4" => "100"
  ]
}

I need to group it and get a result like this:

Collection {#250 ▼
      #items: array:4 [▼
        "CASSETE_1 / CASSETE_2" => "500"
        "CASSETE_3 / CASSETE_4" => "100"
      ]
    }

Is that possible?

I used unique() but the result is:

Collection {#251 ▼
  #items: array:2 [▼
    "CASSETE_1" => "500"
    "CASSETE_3" => "100"
  ]
}

Upvotes: 0

Views: 834

Answers (3)

mickmackusa
mickmackusa

Reputation: 47874

This can be accomplished wholly with Laravel's collection methods. Use mapToGroups() to group by amounts, then call mapWithKeys() with implode() to form the desired associative structure with delimited keys.

Code: (PHPize Demo)

$collection = collect([
    "CASSETE_1" => "500",
    "CASSETE_2" => "500",
    "CASSETE_3" => "100",
    "CASSETE_4" => "100",
]);
var_export(
    $collection->mapToGroups(fn($amt, $cassete) => [$amt => $cassete])
    ->mapWithKeys(fn($cassetes, $amt) => [$cassetes->implode(' / ') => $amt])
    ->toArray()
);

Output:

array (
  'CASSETE_1 / CASSETE_2' => 500,
  'CASSETE_3 / CASSETE_4' => 100,
)

Upvotes: 0

Andy
Andy

Reputation: 2593

Try this below ( convert the collection into Array first ) :

$input = [
    "CASSETE_1" => "500",
    "CASSETE_2" => "500",
    "CASSETE_3" => "100",
    "CASSETE_4" => "100",
  ];

$values = array_unique(array_values($input));

 // output results 
$output =[];
foreach ($values as $v) {
    $index = implode(", ", array_keys($input, $v));
     $output[$index] = $v;
}

print_r($output);

The output should be:

Array ( [CASSETE_1, CASSETE_2] => 500, [CASSETE_3, CASSETE_4] => 100 )

You should be able to construct the index string that you want by changing the ',' with the character that you need.

Upvotes: 0

sumit
sumit

Reputation: 15464

There is no native way to do that , you need to make custom function. This is what I did

1 Convert collection to array

2 Flip it

3 Filter by value and join them by /

4 flip it again

$arr=array("CASSETE_1" => "500",
    "CASSETE_2" => "500",
    "CASSETE_3" => "100",
    "CASSETE_4" => "100");
$result = array();
foreach (array_flip($arr) as $k=>$v) {
          $result[$k] = implode("/",array_keys(array_filter($arr, function($elem) use($k){
          return $elem == $k;
         })));
}
echo "<pre>";
print_r(array_flip($result));

output

Array
(
    [CASSETE_1/CASSETE_2] => 500
    [CASSETE_3/CASSETE_4] => 100
)

Upvotes: 1

Related Questions