Php's Array_Map Including Keys

Access first level keys with array_map() without calling `array_keys()`

Not with array_map, as it doesn't handle keys.

array_walk does:

$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
array_walk($test_array, function(&$a, $b) { $a = "$b loves $a"; });
var_dump($test_array);

// array(2) {
// ["first_key"]=>
// string(27) "first_key loves first_value"
// ["second_key"]=>
// string(29) "second_key loves second_value"
// }

It does change the array given as parameter however, so it's not exactly functional programming (as you have the question tagged like that). Also, as pointed out in the comment, this will only change the values of the array, so the keys won't be what you specified in the question.

You could write a function that fixes the points above yourself if you wanted to, like this:

function mymapper($arrayparam, $valuecallback) {
$resultarr = array();
foreach ($arrayparam as $key => $value) {
$resultarr[] = $valuecallback($key, $value);
}
return $resultarr;
}

$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
$new_array = mymapper($test_array, function($a, $b) { return "$a loves $b"; });
var_dump($new_array);

// array(2) {
// [0]=>
// string(27) "first_key loves first_value"
// [1]=>
// string(29) "second_key loves second_value"
// }

array_map with access to keys

I'm afraid array_walk() IS the way to do this.

If you don't like array_walk() and insist on doing it with array_map(), well, it's possible. It involves using also array_keys(), array_values() and array_combine(), it is long and ugly but doable:

$myNewArray = array_combine(
array_keys($myArray),
array_map(
function($key, $value) {
if ($key == 'key1') {
$value['newkey'] = 'only for key1';
}
return $value;
},
array_keys($myArray),
array_values($myArray) // can omit array_values() and use $myArray
)
);

You can also do it using array_reduce() but it's the same mess:

$myNewArray = array_reduce(
array_keys($myArray),
function (array $carry, $key) use ($myArray) {
$value = $myArray[$key];
if ($key == 'key1') {
$value['newkey'] = 'only for key1';
}
$carry[$key] = $value;
return $carry;
},
array()
);

I hope you have a condition more complex than $key == 'key1' because only for this it is not worth it writing complex traversal. Isn't it easier to just access the right element and modify it?

$myArray['key1']['newkey'] = 'only for key1';

How to modify index keys using array_map() in PHP

What about the following:


$desired_output = array();
array_walk(
$data,
function(&$val, $key) use (&$desired_output)
{
$len = strlen('posted_');
if (substr($key, 0, $len) == "posted_") {
$key = substr($key, $len);
}
$desired_output[$key] = $val;
}
);

print_r($desired_output);

Changes:

  • Using array_walk instead of array_map since _map cannot handle keys
  • Creating an empty array to build the result in
  • Using that array in the scope of the lambda function
  • Replacing the "posted_" only if it exists in the key

Output:

$ php -f ~/tmp/so2.php

Array
(
[name] => John Doe
[age] => 30
)

Array mapping in PHP with keys

Just use array_reduce:

$obj1 = new stdClass;
$obj1 -> id = 12;
$obj1 -> name = 'Lorem';
$obj1 -> email = 'lorem@example.org';

$obj2 = new stdClass;
$obj2 -> id = 34;
$obj2 -> name = 'Ipsum';
$obj2 -> email = 'ipsum@example.org';

$reduced = array_reduce(
// input array
array($obj1, $obj2),
// fold function
function(&$result, $item){
// at each step, push name into $item->id position
$result[$item->id] = $item->name;
return $result;
},
// initial fold container [optional]
array()
);

It's a one-liner out of comments ^^



Related Topics



Leave a reply



Submit