PHP';s数组_映射,包括键
有没有办法做到这一点:PHP';s数组_映射,包括键,php,functional-programming,Php,Functional Programming,有没有办法做到这一点: $test_array = array("first_key" => "first_value", "second_key" => "second_value"); var_dump(array_map(function($a, $b) { return "$a loves $b"; }, array_keys($test_array), array_values($test_
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map(function($a, $b) { return "$a loves $b"; },
array_keys($test_array),
array_values($test_array)));
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\u键
和array\u值
,而是直接传递$test\u数组
变量
所需输出为:
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
我所说的“手动循环”是指编写一个使用foreach
的自定义函数。这将返回一个新数组,如array\u map
那样,因为函数的作用域导致$array
是一个副本而不是引用:
function map($array, callable $fn) {
foreach ($array as $k => &$v) $v = call_user_func($fn, $k, $v);
return $array;
}
您将array\u map
与array\u键一起使用的技术实际上看起来更简单、更强大,因为您可以使用null
作为回调来返回键值对:
function map($array, callable $fn = null) {
return array_map($fn, array_keys($array), $array);
}
不使用array_map,因为它不处理键
是否:
但是,它确实改变了作为参数给定的数组,因此它并不完全是函数式编程(正如您将问题标记为那样)。此外,正如注释中指出的,这只会更改数组的值,因此键不会是您在问题中指定的键
如果愿意,您可以编写一个函数来修复上面的点,如下所示:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map(function($a, $b) { return "$a loves $b"; },
array_keys($test_array),
array_values($test_array)));
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"
// }
基于,以下是我为避免弄乱原始阵列而最终采取的措施:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
$result_array = array();
array_walk($test_array,
function($a, $b) use (&$result_array)
{ $result_array[] = "$b loves $a"; },
$result_array);
var_dump($result_array);
我发现它缺少一个显而易见的答案:
function array_map_assoc(){
if(func_num_args() < 2) throw new \BadFuncionCallException('Missing parameters');
$args = func_get_args();
$callback = $args[0];
if(!is_callable($callback)) throw new \InvalidArgumentException('First parameter musst be callable');
$arrays = array_slice($args, 1);
array_walk($arrays, function(&$a){
$a = (array)$a;
reset($a);
});
$results = array();
$max_length = max(array_map('count', $arrays));
$arrays = array_map(function($pole) use ($max_length){
return array_pad($pole, $max_length, null);
}, $arrays);
for($i=0; $i < $max_length; $i++){
$elements = array();
foreach($arrays as &$v){
$elements[] = each($v);
}
unset($v);
$out = call_user_func_array($callback, $elements);
if($out === null) continue;
$val = isset($out[1]) ? $out[1] : null;
if(isset($out[0])){
$results[$out[0]] = $val;
}else{
$results[] = $val;
}
}
return $results;
}
函数数组\映射\关联(){
如果(func_num_args()<2)抛出new\BadFunctionCallException(“缺少参数”);
$args=func_get_args();
$callback=$args[0];
如果(!is_callable($callback))抛出new\InvalidArgumentException('First parameter must be callable');
$arrays=array\u slice($args,1);
数组(数组、函数和$a){
$a=(数组)$a;
重置(a美元);
});
$results=array();
$max_length=max(数组映射('count',$arrays));
$arrays=数组映射(函数($pole)使用($max\u长度){
返回数组_pad($pole,$max_length,null);
}美元阵列);
对于($i=0;$i<$max_length;$i++){
$elements=array();
foreach($arrays as&$v){
$elements[]=每个($v);
}
未结算(五美元);
$out=调用用户函数数组($callback,$elements);
如果($out==null)继续;
$val=isset($out[1])?$out[1]:null;
如果(isset($out[0])){
$results[$out[0]]=$val;
}否则{
$results[]=$val;
}
}
返回$results;
}
工作原理与数组映射完全相同。差不多
事实上,它并不是像你从其他语言中知道的那样纯粹的map
。Php非常奇怪,所以它需要一些非常奇怪的用户函数,因为我们不想破坏我们精确破坏的方法
实际上,它根本不是地图。然而,它仍然非常有用
- 与数组映射的第一个明显区别是回调从每个输入数组中获取
each()
的输出,而不仅仅是值。您仍然可以一次迭代多个数组
- 第二个区别是从回调返回键后处理键的方式;回调函数的返回值应该是
数组('new\u key','new\u value')
。键可以也将被更改,如果返回相同的键,相同的键甚至会导致覆盖以前的值。这不是常见的map
行为,但它允许您重写键
- 第三个奇怪的事情是,如果您在返回值中省略了
键
(通过数组(1=>'value')
或数组(null,'value')
),则将分配新键,就像使用了$array[]=$value
一样。这也不是map
的常见行为,但我想它有时很方便
- 第四件奇怪的事情是,如果回调函数不返回值,或者返回
null
,那么整个当前键和值集将从输出中忽略,它将被跳过。这项功能完全是非map
py,但如果有这样的功能,它将使该功能成为array\u filter\u assoc
的绝佳特技双倍
- 如果在回调的返回中省略了第二个元素(
1=>…
)(值的部分),则使用null
,而不是实际值
- 除了回调返回中带有键
0
和1
的元素之外,其他元素都将被忽略
- 最后,如果lambda返回除
null
或array之外的任何值,则视为忽略了键和值,因此:
- 已为元素指定新键
null
用作其值
警告:
请记住,这最后一个功能只是以前功能的一个残余,它可能是完全无用的。非常不鼓励依赖此功能,因为此功能将在将来的版本中被随机弃用和意外更改。
注:
与array\u map
不同,传递到array\u map\u assoc
的所有非数组参数(第一个回调参数除外)都以静默方式强制转换到数组
示例:
//TODO:示例,有人吗?
使用PHP5.3或更高版本:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(
array_map(
function($key) use ($test_array) { return "$key loves ${test_array[$key]}"; },
array_keys($test_array)
)
);
我根据以下内容创建了此函数:
例如:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map_(function($key, $value){
return $key . " loves " . $value;
}, $arr));
输出:
array (
'first_key' => 'first_key loves first_value,
'second_key' => 'second_key loves second_value',
)
当然,您可以使用数组_值
准确返回OP想要的内容
array_values(array_map_(function($key, $value){
return $key . " loves " . $value;
}, $test_array))
这可能是最短、最简单的理由:
$states = array('az' => 'Arizona', 'al' => 'Alabama');
array_map(function ($short, $long) {
return array(
'short' => $short,
'long' => $long
);
}, array_keys($states), $states);
// produces:
array(
array('short' => 'az', 'long' => 'Arizona'),
array('short' => 'al', 'long' => 'Alabama')
)
library*非常适合执行此类任务。它是来自.NET的LINQ端口,完全支持所有回调中的值和键,类似于SQL。例如:
$mapped_array = from($test_array)
->select(function ($v, $k) { return "$k loves $v"; })
->toArray();
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map2(function($a, $b) { return "$a loves $b"; }, $test_array));
或者只是:
$mapped_iterator = from($test_array)->select('"$k loves $v"');
这里,“$k爱$v”
是该库支持的完整闭包语法的快捷方式<代码>toArray()
最后是可选的。方法链返回一个迭代器,因此如果只需要使用foreach
对结果进行迭代,则可以删除toArray
调用
*由我开发的以下是我非常简单、兼容PHP 5.5的解决方案:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
可调用的
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
function array_map_assoc_partial(callable $f) {
return function (array $a) use ($f) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
};
}
...
$my_mapping = array_map_assoc_partial($func);
var_dump($my_mapping($ordinals));
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
function array_map_assoc(callable $f, array $a) {
return array_reduce(array_map($f, array_keys($a), $a), function (array $acc, array $a) {
return $acc + $a;
}, []);
}
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
$test_array = ["first_key" => "first_value",
"second_key" => "second_value"];
$array_map_assoc = function (callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
};
$f = function ($key, $value) {
return [$key, $key . ' loves ' . $value];
};
var_dump(array_values($array_map_assoc($f, $test_array)));
$test_array = ["first_key" => "first_value",
"second_key" => "second_value"];
$array_map_assoc = function (callable $f, array $a) {
return array_map($f, array_keys($a), $a);
};
$f = function ($key, $value) {
return $key . ' loves ' . $value;
};
var_dump($array_map_assoc($f, $test_array));
/**
* @param array $array
* @param callable $callback
* @return array
*/
function arrayMap(array $array, callable $callback)
{
$newArray = [];
foreach( $array as $key => $value )
{
$newArray[] = call_user_func($callback, $value, $key, $array);
}
return $newArray;
}
$testArray = [
"first_key" => "first_value",
"second_key" => "second_value"
];
var_dump(
arrayMap($testArray, function($value, $key) {
return $key . ' loves ' . $value;
});
);
function array_map_associative(callable $callback, $array) {
/* map original array keys, and call $callable with $key and value of $key from original array. */
return array_map(function($key) use ($callback, $array){
return $callback($key, $array[$key]);
}, array_keys($array));
}
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
function array_map2(callable $f, array $a)
{
return array_map($f, array_keys($a), $a);
}
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map2(function($a, $b) { return "$a loves $b"; }, $test_array));
$myArray = [
"key0" => 0,
"key1" => 1,
"key2" => 2
];
array_combine(
array_keys($myArray),
array_map(
function ($intVal) {
return strval($intVal);
},
$myArray
)
);
array(3) {
["key0"]=>
string(1) "0"
["key1"]=>
string(1) "1"
["key2"]=>
string(1) "2"
}
$test_array = [
"first_key" => "first_value",
"second_key" => "second_value"
];
$f = function($ar) {
return array_map(
function($key, $val) {
return "{$key} - {$val}";
},
array_keys($ar),
$ar
);
};
#-- WITHOUT preserving keys
$res = $f($test_array);
#-- WITH preserving keys
$res = array_combine(
array_keys($test_array),
$f($test_array)
);
$array = [
'category1' => 'first category',
'category2' => 'second category',
];
$new = array_map(function($key, $value) {
return "{$key} => {$value}";
}, array_keys($array), $array);
$test_array = [
"first_key" => "first_value",
"second_key" => "second_value",
];
$x_result = (function(array $arr) {
foreach ($arr as $key => $value) {
yield "$key loves $value";
}
})($test_array);
var_dump(iterator_to_array($x_result));
// array(2) {
// [0]=>
// string(27) "first_key loves first_value"
// [1]=>
// string(29) "second_key loves second_value"
// }
function xmap(callable $cb, array $arr)
{
foreach ($arr as $key => $value) {
yield $cb($key, $value);
}
}
var_dump(iterator_to_array(
xmap(function($a, $b) { return "$a loves $b"; }, $test_array)
));