knot22
knot22

Reputation: 2768

Create flat, associative array from 2nd level values and 1st level keys of a 2d array

I'm looking for a way to replace nested foreach loops with a functional programming approach. Here is the sample data:

$mode[1] = [1, 2, 5, 6];
$mode[0] = [3, 4, 7, 8];

Currently my code is this:

foreach ($mode as $key => $value):
  foreach ($value as $v):
    $modes[$v] = $key;
  endforeach;
endforeach;

echo '<pre>' . print_r($modes, 1) . '</pre>';

This generates the desired output (which can be thought of as flipping a 2d array):

array (
  1 => 1,
  2 => 1,
  5 => 1,
  6 => 1,
  3 => 0,
  4 => 0,
  7 => 0,
  8 => 0,
)

Does anyone know how the foreach code block can be replaced with a functional programming alternative?

Upvotes: 0

Views: 1399

Answers (4)

mickmackusa
mickmackusa

Reputation: 47991

I think array_walk() partnered with a Union Operator and array_fill_keys() seems like a clean choice for this task:

Code: (Demo)

$mode[1] = [1, 2, 5, 6];
$mode[0] = [3, 4, 7, 8];

$result = []; // declare empty array so that union operator works
array_walk($mode, function($a, $k) use (&$result) { $result += array_fill_keys($a, $k); });
var_export($result);

To avoid declaring any variables in the global scope, call array_reduce() on the first level keys and use those keys to access the second level subarray. (Demo)

var_export(
    array_reduce(
        array_keys($mode),
        fn($result, $k) => $result += array_fill_keys($mode[$k], $k),
        []
    )
);

Output (from either snippet):

array (
  1 => 1,
  2 => 1,
  5 => 1,
  6 => 1,
  3 => 0,
  4 => 0,
  7 => 0,
  8 => 0,
)

Upvotes: 1

Barmar
Barmar

Reputation: 781917

You can do it with array_map()

array_map(function($key, $value) use (&$modes) {
    array_map(function($v) use (&$modes) {
        $modes[$v] = $key;
    }, $value);
}, array_keys($mode), array_values($mode));

I'm not sure why you would want to do this, the foreach version seems much clearer to me.

Upvotes: 2

Marijke Luttekes
Marijke Luttekes

Reputation: 1293

I'd use array_fill_keys to create the mode arrays, then merge them into one:

$modes = array_fill_keys($mode[1], 1) + array_fill_keys($mode[0], 0);

For legibility, you can split it up into multiple lines, but this should get you an idea.

Bonus: you can abstract this code even more, if you don't know the contents of $mode exactly:

$modes = [];
foreach ($mode as $key => $value) {
    $modes += array_fill_keys($value, $key);
}

Upvotes: 0

andreas karimi
andreas karimi

Reputation: 192

use array_flip for exchange key and val together in array :

https://3v4l.org/DeIsG

but because of you want use multidimensional array you should have a loop :

<?php
$mode[0] = array(1, 2, 5, 6);
$mode[1] = array(3, 4, 7, 8);
for($i=0;$i<2;$i++)
{
 $flipped = array_flip($mode[$i]);
 print_r($flipped);
}

?>

output:

Array
(
[1] => 0
[2] => 1
[5] => 2
[6] => 3
)
Array
(
[3] => 0
[4] => 1
[7] => 2
[8] => 3
)

Upvotes: -4

Related Questions