4

I have a flat associative array which may contain duplicate values.

Array (
    [for-juniors] => product_category 
    [for-men] => product_category
    [coats] => product_category
    [for-women] => product_category
    [7-diamonds] => brand
) 

I need to restructure the data to store the original values as new keys and the original keys pushed into subarrays associated with the new keys.

array(
    'product_category' => array(
        'for-juniors',
        'for-men',
        'coats',
        'for-women'
    ),
    'brand' => array(
        '7-diamonds'
    )
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Ahmed Fouad
  • 2,963
  • 10
  • 30
  • 54

3 Answers3

6
$grouped = array();
foreach ($input as $choice => $group) {
    $grouped[$group][] = $choice;
}

var_dump($grouped);
deceze
  • 510,633
  • 85
  • 743
  • 889
1

Because within a foreach() loop, the values are declared BEFORE the keys, you can actually populate the new data structure with a body-less foreach() loop.

Code: (Demo)

$array = [
    'for-juniors' => 'product_category',
    'for-men' => 'product_category',
    'coats' => 'product_category',
    'for-women' => 'product_category',
    '7-diamonds' => 'brand'
];

$grouped = [];
foreach ($array as $grouped[$group][] => $group);
var_export($grouped);

Output:

array (
  'product_category' => 
  array (
    0 => 'for-juniors',
    1 => 'for-men',
    2 => 'coats',
    3 => 'for-women',
  ),
  'brand' => 
  array (
    0 => '7-diamonds',
  ),
)
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

This'll do:

function array_flip_safe(array $array) : array
{
    return array_reduce(array_keys($array), function ($carry, $key) use (&$array) {
        $carry[$array[$key]] ??= []; // PHP 7.0 - ^7.3: $carry[$array[$key]] = $carry[$array[$key]] ?? [];
        $carry[$array[$key]][] = $key;
        return $carry;
    }, []);
}

The callback creates an empty array if the array doesn't already exist. Then it appends current iteration's $key ($value of array_keys($array)) to that array.

Here's an example for better understanding:

$businessHours = [
    'mo' => '13:00 - 16:00',
    'tu' => '8:00 - 12:00',
    'we' => '13:00 - 16:00',
    'th' => '8:00 - 12:00',
    'fr' => '13:00 - 16:00',
    'sa' => '',
    'su' => '',
];

$flipped = array_flip_safe($businessHours);

ray($flipped); (or var_dump, var_export, etc.) outputs:

array:3 [▼
  "13:00 - 16:00" => array:3 [▼
    0 => "mo"
    1 => "we"
    2 => "fr"
  ]
  "8:00 - 12:00" => array:2 [▼
    0 => "tu"
    1 => "th"
  ]
  "" => array:2 [▼
    0 => "sa"
    1 => "su"
  ]
]

Note that the order of inner arrays' values is the same as the order of original array's keys.

s3c
  • 1,481
  • 19
  • 28