2

I'm trying to flip array but it missed value from the key with the same name. What do I have to use, to add couple values to key which occur multiple times in array?

For example, for

[
    "Input.txt" => "Randy",
    "Code.py" => "Stan",
    "Output.txt" => "Randy"
]

the groupByOwners function should return

[
    "Randy" => ["Input.txt", "Output.txt"],
    "Stan" => ["Code.py"]
]

The current code:

class FileOwners
{
    static $files;
    public static function groupByOwners($files)
    {
       $flip = array_flip($files);
        print_r($flip);
    }
}

    $files = array
    (
        "Input.txt" => "Randy",
        "Code.py" => "Stan",
        "Output.txt" => "Randy"
    );

My function return Array ( [Randy] => Output.txt [Stan] => Code.py ) NULL.

So value "Input.txt" is missing. It has to be the same key for both values, so how can I put "Input.txt" with "Output.txt" in array for key [Randy]?

MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
elBrambore
  • 110
  • 2
  • 8
  • Welcome to SO! Good question. One thing you should always provide is the _desired output_ (similar to the way you provided `$files`). The answer can vary depending on if it's OK for _all_ array elements to become an array of values or not. – random_user_name Nov 30 '17 at 14:16
  • @cale_b It's a bit hidden but "the groupByOwners function should return `["Randy" => ["Input.txt", "Output.txt"], "Stan" => ["Code.py"]]`" – MonkeyZeus Nov 30 '17 at 14:18

2 Answers2

3

You will have to loop it yourself and build a new array:

$files = array(
    "Input.txt" => "Randy",
    "Code.py" => "Stan",
    "Output.txt" => "Randy"
);

$new_files = array();

foreach($files as $k=>$v)
{
    $new_files[$v][] = $k;
}

print_r($new_files);
MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
  • Mild warning, probably not an issue - but `isset` will return FALSE if the value is `NULL`. – random_user_name Nov 30 '17 at 14:14
  • Your `array_key_exists` syntax is wrong but you don't need that nor the `if` statement, you can simply use `$new_files[$v][] = $k;` in the loop. There is no need to initialize arrays in your array. – jeroen Nov 30 '17 at 14:26
  • 1
    @jeroen At times, I forget that PHP has such forgiving constructs. Your feedback is much appreciated. – MonkeyZeus Nov 30 '17 at 14:30
  • Ok, now i get it. Thank you for you help! It's simple and understable for me as a beginner. I saw your edition of my post. Sorry for mistakes, will remember how to post question correctly next time. Thanks! – elBrambore Dec 02 '17 at 15:29
0

A somewhat quick and a little hacky solution:

php >  $files = array
php >     (
php (         "Input.txt" => "Randy",
php (         "Code.py" => "Stan",
php (         "Output.txt" => "Randy"
php (     );
php > var_dump(array_reduce(array_keys($files), function($p, $c) use (&$files) { $p[$files[$c]] = $p[$files[$c]] ?? []; $p[$files[$c]][] = $c; return $p;  }, []));
array(2) {
  ["Randy"]=>
  array(2) {
    [0]=>
    string(9) "Input.txt"
    [1]=>
    string(10) "Output.txt"
  }
  ["Stan"]=>
  array(1) {
    [0]=>
    string(7) "Code.py"
  }
}

NB: The use of '??' requires PHP 7.0.

Just to pull the important part out of the one-liner and make it at least slightly more readable:

array_reduce(array_keys($files), function($p, $c) uses (&$files) {
     $p[$files[$c]] = $p[$files[$c]] ?? []; 
     $p[$files[$c]][] = $c;
}, []);

You could just as easily use the if(isset(...)) logic to ensure the array element in $p exists.

kmdm
  • 143
  • 7