ต่อไปนี้เป็นโซลูชันที่ใช้งานร่วมกับ PHP 5.5 ได้อย่างง่ายดาย
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
callable 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]
แทน ผลของการทำแผนที่ callable array_merge
เป็นแล้วก็แตกและส่งผ่านไปยัง ก่อนหน้านี้การส่งคืนคีย์ที่ซ้ำกันจะส่งผลให้ได้รับรางวัลในภายหลัง
nb Alex83690 ได้ระบุไว้ในความคิดเห็นว่าการใช้array_replace
ที่นี่แทนการarray_merge
เก็บรักษาคีย์จำนวนเต็ม array_replace
ไม่ได้แก้ไขอาร์เรย์อินพุตดังนั้นจึงปลอดภัยสำหรับโค้ดการทำงาน
หากคุณใช้ PHP 5.3 ถึง 5.5 สิ่งต่อไปนี้จะเทียบเท่า มันใช้array_reduce
และตัว+
ดำเนินการอาร์เรย์แบบไบนารีเพื่อแปลงอาร์เรย์แบบสองมิติที่เป็นผลลัพธ์ลงในอาร์เรย์แบบหนึ่งมิติในขณะที่ยังคงคีย์ไว้:
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));
ดังนั้นคำตอบคือไม่คุณไม่สามารถหลีกเลี่ยงการโทรarray_keys
ได้ แต่คุณสามารถสรุปสถานที่ที่array_keys
ได้รับการโทรเข้าสู่ฟังก์ชั่นการสั่งซื้อที่สูงขึ้นซึ่งอาจจะดีพอ