[php] 키를 포함한 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_keysarray_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_mapwith를 사용 하는 기술 array_keys은 실제로 더 단순 해 보이며 null키-값 쌍을 반환하는 콜백으로 사용할 수 있기 때문에 더 강력합니다 .

function map($array, callable $fn = null) {
  return array_map($fn, array_keys($array), $array);
}