[php] array_map, array_walk 및 array_filter의 차이점
정확히 어떤 것은 사이의 차이입니다 array_map
, array_walk
하고 array_filter
. 설명서에서 볼 수있는 것은 제공된 배열에서 작업을 수행하기 위해 콜백 함수를 전달할 수 있다는 것입니다. 그러나 나는 그들 사이에 특별한 차이점을 찾지 못하는 것 같습니다.
그들은 같은 일을 수행합니까?
그것들을 서로 바꿔서 사용할 수 있습니까?
예시가 다른 경우 귀하의 도움에 감사드립니다.
답변
- 값 변경 :
array_map
가능한 동안 입력 배열 내부의 값을 변경할 수 없습니다array_walk
. 특히,array_map
논쟁을 바꾸지 마십시오.
- 어레이 키 액세스 :
array_map
어레이 키로 작동 할 수 없습니다array_walk
.
- 반환 값 :
array_map
새 배열을 반환하고array_walk
만 반환합니다true
. 따라서 하나의 배열을 통과 한 결과 배열을 만들지 않으려면을 사용해야합니다array_walk
.
- 여러 배열 반복
array_map
또한 임의의 수의 배열을 수신 할 수 있으며 병렬로 반복 할 수 있지만array_walk
하나에서만 작동합니다.
- 임의의 데이터를 콜백으로 전달 :
array_walk
콜백에 전달할 추가 임의의 매개 변수를 수신 할 수 있습니다. 이것은 PHP 5.3 ( 익명 함수 가 도입 되었을 때) 이래로 대부분 관련이 없습니다 .
- 반환 된 배열의 길이 :
- 결과 배열은
array_map
가장 큰 입력 배열과 길이가 같습니다.array_walk
배열을 반환하지 않지만 동시에 원래 배열의 요소 수를 변경할 수 없습니다.array_filter
필터링 함수에 따라 배열 요소의 하위 집합 만 선택합니다. 키를 유지합니다.
- 결과 배열은
예:
<pre>
<?php
$origarray1 = array(2.4, 2.6, 3.5);
$origarray2 = array(2.4, 2.6, 3.5);
print_r(array_map('floor', $origarray1)); // $origarray1 stays the same
// changes $origarray2
array_walk($origarray2, function (&$v, $k) { $v = floor($v); });
print_r($origarray2);
// this is a more proper use of array_walk
array_walk($origarray1, function ($v, $k) { echo "$k => $v", "\n"; });
// array_map accepts several arrays
print_r(
array_map(function ($a, $b) { return $a * $b; }, $origarray1, $origarray2)
);
// select only elements that are > 2.5
print_r(
array_filter($origarray1, function ($a) { return $a > 2.5; })
);
?>
</pre>
결과:
Array
(
[0] => 2
[1] => 2
[2] => 3
)
Array
(
[0] => 2
[1] => 2
[2] => 3
)
0 => 2.4
1 => 2.6
2 => 3.5
Array
(
[0] => 4.8
[1] => 5.2
[2] => 10.5
)
Array
(
[1] => 2.6
[2] => 3.5
)
답변
함수를 데이터 배열 에 매핑 한다는 아이디어는 함수형 프로그래밍에서 비롯됩니다. 배열의 각 요소에 대해 함수를 호출 array_map
하는 foreach
루프 로 생각해서는 안됩니다 (구현 방법 임에도 불구하고). 배열의 각 요소에 독립적으로 함수를 적용하는 것으로 생각해야합니다.
이론적으로 함수 매핑과 같은 것은 데이터에 적용되는 함수가 전역 상태가 아닌 데이터에만 영향을 미치기 때문에 병렬로 수행 될 수 있습니다. 왜냐하면 array_map
PHP에서는 그렇지 않더라도 항목에 함수를 적용하는 순서를 선택할 수 있기 때문 입니다.
array_walk
반면에 데이터 배열을 처리하는 것과 정반대의 접근 방식입니다. 각 항목을 개별적으로 처리하는 대신 상태 ( &$userdata
)를 사용 하고 foreach 루프와 같이 해당 위치에서 항목을 편집 할 수 있습니다. 항목이 $funcname
적용될 때마다 프로그램의 전역 상태가 변경 될 수 있으므로 항목을 처리하는 올바른 단일 방법이 필요 합니다.
PHP 땅으로 돌아가서 데이터 반복을 더 잘 제어 할 수 있다는 점을 제외 array_map
하고 array_walk
는 거의 동일 array_walk
하며 일반적으로 새로운 “변경된”배열을 반환하는 대신 데이터를 “변경”하는 데 사용됩니다.
array_filter
실제로 array_walk
(또는 array_reduce
) 의 응용 프로그램이며 편의상 제공되는 것입니다.
답변
설명서에서
bool array_walk (배열 & $ array, 콜백 $ funcname [, 혼합 $ userdata]) <-return bool
array_walk 는 배열과 함수를 받아서F
모든 요소 x를로 대체하여 수정합니다 F(x)
.
배열 array_map (콜백 $ callback, 배열 $ arr1 [, 배열 $ …]) <-배열 반환
array_map 은 위치를 수정하는 대신 변환 된 요소가 포함 된 새 배열을 반환한다는 점을 제외하고 는 똑같은 작업 을 수행합니다.
배열 array_filter (배열 $ input [, 콜백 $ callback]) <-배열을 반환
F
요소를 변환하는 대신 function을 가진 array_filterF(x)
는 true가 아닌 요소를 제거 합니다.
답변
다른 답변은 array_walk (in-place modified)와 array_map (return modified copy)의 차이점을 잘 보여줍니다. 그러나 그들은 실제로 array_map과 array_filter를 이해하는 조명 방법 인 array_reduce를 언급하지 않습니다.
array_reduce 함수는 다음과 같이 배열, 두 개의 인수 함수 및 ‘누산기’를 사용합니다.
array_reduce(array('a', 'b', 'c', 'd'),
'my_function',
$accumulator)
배열의 요소는 주어진 함수를 사용하여 한 번에 하나씩 누산기와 결합됩니다. 위의 호출 결과는 다음과 같습니다.
my_function(
my_function(
my_function(
my_function(
$accumulator,
'a'),
'b'),
'c'),
'd')
루프와 관련하여 생각하고 싶다면 다음과 같습니다 (배열 _reduce를 사용할 수없는 경우 실제로 이것을 폴백으로 사용했습니다).
function array_reduce($array, $function, $accumulator) {
foreach ($array as $element) {
$accumulator = $function($accumulator, $element);
}
return $accumulator;
}
이 루핑 버전을 사용하면 왜 세 번째 인수를 ‘누산기’라고 불렀는지 알 수 있습니다. 각 반복을 통해 결과를 누적하는 데 사용할 수 있습니다.
그렇다면 이것이 array_map 및 array_filter와 어떤 관련이 있습니까? 그것들은 둘 다 특정 종류의 array_reduce입니다. 다음과 같이 구현할 수 있습니다.
array_map($function, $array) === array_reduce($array, $MAP, array())
array_filter($array, $function) === array_reduce($array, $FILTER, array())
array_map과 array_filter가 다른 순서로 인수를 취한다는 사실을 무시하십시오. 그것은 PHP의 또 다른 단점입니다. 중요한 점은 오른쪽이 $ MAP 및 $ FILTER라는 함수를 제외하고는 동일하다는 것입니다. 그래서 그들은 어떻게 생겼습니까?
$MAP = function($accumulator, $element) {
$accumulator[] = $function($element);
return $accumulator;
};
$FILTER = function($accumulator, $element) {
if ($function($element)) $accumulator[] = $element;
return $accumulator;
};
보시다시피, 두 함수 모두 $ accumulator를 가져 와서 다시 반환합니다. 이 기능에는 두 가지 차이점이 있습니다.
- $ MAP는 항상 $ accumulator에 추가되지만 $ FILTER는 $ function ($ element)가 TRUE 인 경우에만 추가합니다.
- $ FILTER는 원래 요소를 추가하지만 $ MAP는 $ function ($ element)를 추가합니다.
이것은 쓸모없는 상식과는 거리가 멀다. 알고리즘을보다 효율적으로 만드는 데 사용할 수 있습니다!
우리는 종종 다음 두 가지 예제와 같은 코드를 볼 수 있습니다.
// Transform the valid inputs
array_map('transform', array_filter($inputs, 'valid'))
// Get all numeric IDs
array_filter(array_map('get_id', $inputs), 'is_numeric')
루프 대신 array_map 및 array_filter를 사용하면 이러한 예제가 매우 멋지게 보입니다. 그러나 첫 번째 호출 (맵 또는 필터)이 $ inputs를 통과하고 중간 배열을 작성하므로 $ inputs가 큰 경우 매우 비효율적 일 수 있습니다. 이 중간 배열은 두 번째 호출로 바로 전달되어 전체를 다시 통과 한 다음 중간 배열을 가비지 수집해야합니다.
array_map과 array_filter가 모두 array_reduce의 예라는 사실을 이용하여이 중간 배열을 제거 할 수 있습니다. 이들을 결합하면 각 예제에서 $ inputs를 한 번만 통과하면됩니다.
// Transform valid inputs
array_reduce($inputs,
function($accumulator, $element) {
if (valid($element)) $accumulator[] = transform($element);
return $accumulator;
},
array())
// Get all numeric IDs
array_reduce($inputs,
function($accumulator, $element) {
$id = get_id($element);
if (is_numeric($id)) $accumulator[] = $id;
return $accumulator;
},
array())
참고 : array_map은 한 번에 하나의 배열 만 처리 할 수 있고 array_filter는 기본 $ 함수로 “empty”를 사용하지 않기 때문에 위의 array_map 및 array_filter 구현은 PHP와 동일하게 작동하지 않습니다. 또한 키를 유지하지 않습니다.
그것들을 PHP처럼 동작시키는 것은 어렵지 않지만, 이러한 합병증으로 인해 핵심 아이디어를 찾기가 더 어려워 질 것이라고 생각했습니다.
답변
다음 개정판은 PHP의 array_filer (), array_map () 및 array_walk ()를보다 명확하게 설명합니다.이 모두는 함수형 프로그래밍에서 시작되었습니다.
array_filter ()는 데이터를 필터링하여 다음과 같이 이전 배열의 원하는 항목 만 보유하는 새 배열을 생성합니다.
<?php
$array = array(1, "apples",2, "oranges",3, "plums");
$filtered = array_filter( $array, "ctype_alpha");
var_dump($filtered);
?>
여기에 라이브 코드
모든 숫자 값은 $ array에서 필터링되고 $ filtered는 과일 유형 만 남습니다.
array_map ()도 새로운 배열을 생성하지만 array_filter ()와 달리 결과 배열에는 $ filtered 입력의 모든 요소가 포함 되지만 다음과 같이 각 요소에 콜백을 적용하기 때문에 값이 변경됩니다.
<?php
$nu = array_map( "strtoupper", $filtered);
var_dump($nu);
?>
여기에 라이브 코드
이 경우 코드는 내장 strtoupper ()를 사용하여 콜백을 적용하지만 사용자 정의 함수도 또 다른 실행 가능한 옵션입니다. 콜백은 $ filtered의 모든 항목에 적용되므로 요소에 대문자 값이 포함 된 $ nu를 생성합니다.
다음 스 니펫에서 array walk ()는 $ nu를 통과하고 참조 연산자 ‘&’에 대해 각 요소를 변경합니다. 추가 배열을 만들지 않고 변경 사항이 발생합니다. 모든 요소의 값은 키, 범주 및 값을 지정하는보다 유익한 문자열로 변경됩니다.
<?php
$f = function(&$item,$key,$prefix) {
$item = "$key: $prefix: $item";
};
array_walk($nu, $f,"fruit");
var_dump($nu);
?>
데모 보기
참고 : array_walk ()에 대한 콜백 함수는 array_walk ()에 의해 호출 될 때 요소의 값과 키를 자동으로 획득하는 두 개의 매개 변수를 사용합니다. (자세한 내용은 여기를 참조 하십시오 ).