키를 포함한 PHP의 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)));
하지만 그 대신 호출 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));
}
eis의 답변을 바탕으로 원래 배열을 엉망으로 만들지 않기 위해 내가 한 일은 다음과 같습니다.
$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);
"수동 루프"는을 사용하는 사용자 정의 함수를 작성하는 것을 의미했습니다 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);
}
YaLinqo 라이브러리 *는 이러한 종류의 작업에 적합합니다. 모든 콜백에서 값과 키를 완전히 지원하고 SQL과 유사한 .NET의 LINQ 포트입니다. 예를 들면 다음과 같습니다.
$mapped_array = from($test_array)
->select(function ($v, $k) { return "$k loves $v"; })
->toArray();
또는 그냥 :
$mapped_iterator = from($test_array)->select('"$k loves $v"');
다음 '"$k loves $v"'
은이 라이브러리가 지원하는 전체 클로저 구문에 대한 바로 가기입니다. toArray()
결국 선택 사항입니다. 메소드 체인은 결과가 바로 사용을 통해 반복 할 필요가 그렇다면, 반복자를 반환 foreach
, toArray
호출이 제거 될 수있다.
* 나에 의해 개발
eis의 답변을 기반 으로이 기능을 만들었습니다 .
function array_map_($callback, $arr) {
if (!is_callable($callback))
return $arr;
$result = array_walk($arr, function(&$value, $key) use ($callback) {
$value = call_user_func($callback, $key, $value);
});
if (!$result)
return false;
return $arr;
}
예:
$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',
)
물론 array_values
OP에서 원하는 것을 정확하게 반환 하는 데 사용할 수 있습니다 .
array_values(array_map_(function($key, $value){
return $key . " loves " . $value;
}, $test_array))
나는 이런 식으로 할 것입니다 :
<?php
/**
* array_map_kv()
* An array mapping function to map with both keys and values.
*
* @param $callback callable
* A callback function($key, $value) for mapping values.
* @param $array array
* An array for mapping.
*/
function array_map_kv(callable $callback, array $array) {
return array_map(
function ($key) use ($callback, $array) {
return $callback($key, $array[$key]); // $callback($key, $value)
},
array_keys($array)
);
}
// use it
var_dump(array_map_kv(function ($key, $value) {
return "{$key} loves {$value}";
}, array(
"first_key" => "first_value",
"second_key" => "second_value",
)));
?>
결과 :
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);
}
질문에서 언급했듯이 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));
버전 5.6 이상을 사용하여 문제에 대한 또 다른 솔루션을 추가하겠습니다. 그것이 이미 훌륭한 솔루션보다 더 효율적인지 모르겠지만 (아마도 그렇지는 않지만) 나에게 읽는 것이 더 간단합니다.
$myArray = [
"key0" => 0,
"key1" => 1,
"key2" => 2
];
array_combine(
array_keys($myArray),
array_map(
function ($intVal) {
return strval($intVal);
},
$myArray
)
);
strval()
의 예제 함수로 사용하면 array_map
다음이 생성됩니다.
array(3) {
["key0"]=>
string(1) "0"
["key1"]=>
string(1) "1"
["key2"]=>
string(1) "2"
}
잘만되면 나는 이것을 이해하기가 아주 쉬운 사람이 아니길 바란다. 키 배열과 값 배열로 배열을 array_combine
만듭니다. key => value
나머지는 설명이 필요 없습니다.
이 배열 라이브러리 에서 map 메소드를 사용 하여 원하는 것을 정확하게 달성 할 수 있습니다.
Arr::map($test_array, function($a, $b) { return "$a loves $b"; });
또한 키를 유지하고 필요에 맞는 몇 가지 다른 모드는 말할 것도없고 새로운 배열을 반환합니다.
나는 항상 배열 맵의 자바 스크립트 변형을 좋아합니다. 가장 간단한 버전은 다음과 같습니다.
/**
* @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;
});
);
키를 유지하면서 이것을하는 또 다른 방법 :
$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)
);
나는 명백한 대답이 누락 된 것을 본다.
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;
}
array_map과 동일하게 작동합니다. 거의.
실제로 map
다른 언어에서 알 수 있듯이 순수하지 않습니다 . Php는 매우 이상하기 때문에 매우 이상한 사용자 기능이 필요합니다 worse is better
. 정확하게 깨진 접근법 을 깨뜨리고 싶지 않기 때문 입니다.
실제로 실제로 map
는 아닙니다 . 그러나 여전히 매우 유용합니다.
array_map과의 첫 번째 명백한 차이점은 콜백은
each()
값이 아닌 모든 입력 배열에서 출력을 얻는다는 것입니다. 한 번에 더 많은 배열을 반복 할 수 있습니다.두 번째 차이점은 키가 콜백에서 반환 된 후 처리되는 방식입니다. 콜백 함수의 반환 값은이어야합니다
array('new_key', 'new_value')
. 동일한 키가 반환되면 동일한 키로 인해 이전 값을 덮어 쓸 수도 있습니다. 일반적인map
동작 은 아니지만 키를 다시 쓸 수 있습니다.세 번째 이상한 점은
key
반환 값 (array(1 => 'value')
또는로array(null, 'value')
) 을 생략하면 새 키가$array[] = $value
사용 된 것처럼 할당 됩니다. 그것은map
일반적인 행동 이 아니지만 때로는 편리하다고 생각합니다.네 번째 이상한 점은 콜백 함수가 값을 반환하지 않거나를 반환하면
null
현재 키와 값의 전체 세트가 출력에서 생략되고 단순히 건너 뜁니다. 이 기능은 완전히map
파이가 아니지만array_filter_assoc
그러한 기능이 있다면 이 기능을 탁월한 스턴트 더블로 만들 것 입니다.콜백의 리턴에서 두 번째 요소 (
1 => ...
) ( 값 부분) 를 생략하면null
실제 값 대신 사용됩니다.키가
0
있고1
콜백이 반환 된 요소를 제외한 다른 요소 는 무시됩니다.마지막으로 람다
null
또는 배열을 제외한 값을 반환하면 키와 값이 모두 생략 된 것처럼 처리됩니다.- 요소의 새 키가 할당됩니다
null
가치로 사용됩니다
경고 :
이 마지막 기능은 이전 기능의 일부일 뿐이며 완전히 쓸모가 없음을 명심하십시오. 이 기능은 향후 릴리스에서 임의로 사용되지 않으며 예기치 않게 변경 되므로이 기능을 사용하지 않는 것이 좋습니다 .
참고 :
와 달리 첫 번째 콜백 매개 변수를 제외하고에 array_map
전달 된 모든 비 배열 매개 변수 array_map_assoc
는 자동으로 배열로 캐스트됩니다.
예 :
// TODO: examples, anyone?
참고 URL : https://stackoverflow.com/questions/13036160/phps-array-map-include-keys
'IT' 카테고리의 다른 글
'box-shadow-color'속성이 있습니까? (0) | 2020.05.23 |
---|---|
OS X Lion에서 터미널이 ~ / .bashrc를로드하지 않는 문제를 해결하는 방법 (0) | 2020.05.23 |
문자열에서 주어진 부분 문자열의 발생 횟수 (0) | 2020.05.23 |
파이썬의 'in'연산자를 무시 하시겠습니까? (0) | 2020.05.23 |
몽구스 _id와 문자열 비교 (0) | 2020.05.23 |