다음과 같은 방법이 있습니까?
$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)));
하지만 그 대신 호출 array_keys
및 array_values
직접 전달 $test_array
변수를?
원하는 출력은 다음과 같습니다.
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
답변
array_map은 키를 처리하지 않으므로 사용하지 않습니다.
array_walk 는 다음을 수행합니다.
$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"
// }
그러나 매개 변수로 주어진 배열을 변경하므로 정확하게 프로그래밍되지는 않습니다 (질문이 태그 된 것처럼). 또한 주석에서 지적했듯이 배열의 값만 변경되므로 키는 질문에 지정한 값이 아닙니다.
원하는 경우 다음과 같이 자신 위에 포인트를 수정하는 함수를 작성할 수 있습니다.
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"
// }
답변
이것은 아마도 가장 짧고 가장 쉬운 이유입니다.
$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')
)
답변
다음은 매우 간단한 PHP 5.5 호환 솔루션입니다.
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
제공하는 콜 러블 자체는 두 값을 가진 배열을 반환해야합니다 return [key, value]
. 따라서 내부 호출 array_map
은 배열 배열을 생성합니다. 그런 다음에 의해 단일 차원 배열로 다시 변환됩니다 array_column
.
용법
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
산출
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
부분 적용
다른 배열이지만 동일한 매핑 함수와 함께 함수를 여러 번 사용해야하는 경우 부분 함수 응용 프로그램 ( ‘ currying ‘ 관련 )을 호출하여 호출 할 때만 데이터 배열을 전달할 수 있습니다.
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));
주어진 것과 동일한 출력을 생성 하며 이전 $func
과 $ordinals
같습니다.
참고 : 매핑 된 함수가 서로 다른 두 입력에 대해 동일한 키 를 반환 하면 이후 키 와 관련된 값 이 이깁니다. array_map_assoc
이전 키가 이길 수 있도록 입력 배열과 출력 결과 를 반대로 바꿉니다. (이 예제에서 반환 된 키는 소스 배열의 키를 통합하므로 충돌 할 수 없으며 차례로 고유해야합니다.)
대안
다음은 위의 변형으로 일부에게는 더 논리적이지만 PHP 5.6이 필요합니다.
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
이 변형에서 제공된 함수 (데이터 배열이 매핑되는 함수)는 대신 하나의 행이있는 연관 배열을 반환해야합니다 return [key => value]
. 그런 다음 호출 가능 항목을 매핑 한 결과는 간단히 압축을 풀고로 전달됩니다 array_merge
. 앞서와 같이, 중복 키를 반환하면 나중에 값을 얻습니다.
nb Alex83690은 주석
array_replace
대신 여기 를 사용 하면array_merge
정수 키가 유지 된다는 의견에 주목했습니다 .array_replace
입력 배열을 수정하지 않으므로 기능 코드에 안전합니다.
PHP 5.3 ~ 5.5 인 경우 다음과 같습니다. array_reduce
이진 +
배열 연산자를 사용 하여 키를 유지하면서 결과 2 차원 배열을 1 차원 배열로 변환합니다.
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));
메모 =>
대신 ,
에서 $func
.
출력은 이전과 동일하며 각각 이전과 같은 방식으로 부분적으로 적용 할 수 있습니다.
요약
원래 질문의 목표는 호출되는 더 복잡한 기능을 희생하면서 가능한 한 간단하게 호출을 호출하는 것입니다. 특히 키와 값을 나누지 않고 데이터 배열을 단일 인수로 전달할 수 있습니다. 이 답변의 시작 부분에 제공된 기능 사용 :
$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)));
또는이 질문에 대해서만 array_map_assoc()
출력 키를 삭제 하는 기능을 단순화 할 수 있습니다 . 질문은 요청하지 않기 때문입니다.
$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));
따라서 대답은 NO 이므로 호출을 피할 수 없지만 고차 함수로 호출되는 array_keys
곳을 추상화 할 수 있습니다 array_keys
.
답변
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)
)
);
답변
이것이 내가 프로젝트에서 이것을 구현 한 방법입니다.
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));
}
답변
이봐! 사소한 해결책이 있습니다!
function array_map2(callable $f, array $a)
{
return array_map($f, array_keys($a), $a);
}
질문에서 언급했듯이 array_map
이미 필요한 기능이 이미 있습니다 . 다른 답변은 심각하게 복잡 array_walk
합니다. 기능적이지 않습니다.
용법
귀하의 예에서 기대할 수 있듯이
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map2(function($a, $b) { return "$a loves $b"; }, $test_array));
답변
“수동 루프”는을 사용하는 사용자 정의 함수를 작성하는 것을 의미했습니다 foreach
. array_map
함수의 범위가 $array
참조가 아닌 복사본 이되기 때문에 새로운 배열을 반환합니다 .
function map($array, callable $fn) {
foreach ($array as $k => &$v) $v = call_user_func($fn, $k, $v);
return $array;
}
array_map
with를 사용 하는 기술 array_keys
은 실제로 더 단순 해 보이며 null
키-값 쌍을 반환하는 콜백으로 사용할 수 있기 때문에 더 강력합니다 .
function map($array, callable $fn = null) {
return array_map($fn, array_keys($array), $array);
}
