Apakah ada cara melakukan sesuatu seperti ini:
$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)));
Tapi bukannya memanggil array_keys
dan array_values
, langsung melewati $test_array
variabel?
Output yang diinginkan adalah:
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
php
functional-programming
José Tomás Tocino
sumber
sumber
Jawaban:
Tidak dengan array_map, karena tidak menangani kunci.
array_walk tidak:
Itu memang mengubah array yang diberikan sebagai parameter, jadi itu bukan pemrograman fungsional (karena Anda memiliki pertanyaan yang ditandai seperti itu). Juga, seperti yang ditunjukkan dalam komentar, ini hanya akan mengubah nilai-nilai array, jadi kunci tidak akan menjadi apa yang Anda tentukan dalam pertanyaan.
Anda bisa menulis fungsi yang memperbaiki poin-poin di atas sendiri jika Anda mau, seperti ini:
sumber
$a = "$b loves $a"
mencocokkan output yang diinginkan OP.array_walk()
tidak mengembalikan array yang dihasilkan, tetapi bool sebagai gantinya.Ini mungkin yang terpendek dan termudah untuk dipikirkan:
sumber
array_keys()
. Tapi sepertinya itu persyaratan konyol.Inilah solusi PHP 5.5-kompatibel saya yang sangat sederhana:
Callable yang Anda berikan harus mengembalikan array dengan dua nilai, yaitu
return [key, value]
. Karena itu panggilan batin untukarray_map
menghasilkan array array. Ini kemudian akan dikonversi kembali ke array dimensi tunggal oleharray_column
.Pemakaian
Keluaran
Aplikasi sebagian
Jika Anda perlu menggunakan fungsi berkali-kali dengan array yang berbeda tetapi fungsi pemetaan yang sama, Anda bisa melakukan sesuatu yang disebut aplikasi fungsi parsial (terkait dengan ' currying '), yang memungkinkan Anda untuk hanya memasukkan array data setelah doa:
Yang menghasilkan output yang sama, diberikan
$func
dan$ordinals
sama seperti sebelumnya.CATATAN: jika fungsi Anda yang dipetakan mengembalikan kunci yang sama untuk dua input berbeda, nilai yang terkait dengan kunci nanti akan menang. Membalikkan array input dan hasil output
array_map_assoc
untuk memungkinkan kunci sebelumnya untuk menang. (Kunci yang dikembalikan dalam contoh saya tidak dapat bertabrakan karena mereka memasukkan kunci dari array sumber, yang pada gilirannya harus unik.)Alternatif
Berikut ini adalah varian di atas, yang mungkin terbukti lebih logis untuk beberapa orang, tetapi membutuhkan PHP 5.6:
Dalam varian ini, fungsi yang disediakan Anda (di mana array data dipetakan) akan mengembalikan array asosiatif dengan satu baris, yaitu
return [key => value]
. Hasil pemetaan callable kemudian dibongkar dan diteruskan kearray_merge
. Seperti sebelumnya, mengembalikan kunci duplikat akan menghasilkan nilai yang menang kemudian.Jika Anda menggunakan PHP 5.3 hingga 5.5, yang berikut ini setara. Ini menggunakan
array_reduce
dan+
operator array biner untuk mengkonversi array dua dimensi yang dihasilkan ke array satu dimensi sambil mempertahankan kunci:Pemakaian
Kedua varian ini akan digunakan sebagai berikut:
Perhatikan
=>
bukan,
di$func
.Outputnya sama seperti sebelumnya, dan masing-masing dapat diterapkan sebagian dengan cara yang sama seperti sebelumnya.
Ringkasan
Tujuan dari pertanyaan awal adalah untuk membuat doa panggilan sesederhana mungkin, dengan mengorbankan fungsi yang lebih rumit yang dipanggil; khususnya, untuk memiliki kemampuan untuk melewatkan array data sebagai argumen tunggal, tanpa memisahkan kunci dan nilai. Menggunakan fungsi yang disediakan di awal jawaban ini:
Atau, hanya untuk pertanyaan ini, kita dapat menyederhanakan
array_map_assoc()
fungsi yang menjatuhkan kunci output, karena pertanyaan tidak menanyakannya:Jadi jawabannya adalah TIDAK , Anda tidak bisa menghindari panggilan
array_keys
, tetapi Anda bisa mengabstraksikan tempat di manaarray_keys
dipanggil menjadi fungsi tingkat tinggi, yang mungkin cukup baik.sumber
array_merge
denganarray_replace
untuk mempertahankan kunci yang akan menjadi bilangan bulat.Dengan PHP5.3 atau lebih baru:
sumber
Ini adalah bagaimana saya menerapkan ini dalam proyek saya.
sumber
Lihat di sini! Ada solusi sepele!
Sebagaimana dinyatakan dalam pertanyaan,
array_map
sudah persis fungsionalitas yang diperlukan . Jawaban lain di sini serius hal rumit:array_walk
tidak berfungsi.Pemakaian
Persis seperti yang Anda harapkan dari contoh Anda:
sumber
qrrqy_keys()
tidak boleh digunakan untuk #reasonDengan "loop manual" yang saya maksud menulis fungsi kustom yang menggunakan
foreach
. Ini mengembalikan array baru seperti yangarray_map
dilakukan karena ruang lingkup fungsi menyebabkan$array
salinan — bukan referensi:Teknik Anda menggunakan
array_map
denganarray_keys
meskipun sebenarnya tampak lebih sederhana dan lebih kuat karena Anda dapat menggunakannull
sebagai panggilan balik untuk mengembalikan pasangan nilai kunci:sumber
unset( $value )
karena masih ada dalam cakupan yang ditentukan.Berdasarkan jawaban eis , inilah yang akhirnya saya lakukan untuk menghindari mengacaukan array asli:
sumber
array_walk
karena Anda tidak merujuknya pada penutupan.Saya membuat fungsi ini, berdasarkan jawaban eis :
Contoh:
Keluaran:
Tentu saja, Anda dapat menggunakan
array_values
untuk mengembalikan persis apa yang diinginkan OP.sumber
$arr
bertipe array, namun jika Anda mengetikkan petunjuk sebagaicallable
danarray
sebaliknya Anda bisa menjatuhkan centang keis_callable
. Selanjutnya, Anda membuat tugas ke $ value yang kemudian tidak digunakan. Anda harus mengabaikan nilai pengembalian. Ketiga, akan lebih baik untuk melemparkan pengecualian dalam callback daripada mengembalikan false. Anda kemudian akan selalu mengembalikan nilai yang valid atau selalu melempar.Pustaka YaLinqo * sangat cocok untuk tugas semacam ini. Ini adalah port LINQ dari. NET yang sepenuhnya mendukung nilai dan kunci di semua panggilan balik dan menyerupai SQL. Sebagai contoh:
atau hanya:
Di sini,
'"$k loves $v"'
adalah jalan pintas untuk sintaksis penutupan penuh yang didukung perpustakaan ini.toArray()
pada akhirnya adalah opsional. Rantai metode mengembalikan sebuah iterator, jadi jika hasilnya hanya perlu diulangi menggunakanforeach
,toArray
panggilan dapat dihapus.* Dikembangkan oleh saya
sumber
Saya akan melakukan sesuatu seperti ini:
Hasil:
sumber
Saya akan menambahkan solusi lain untuk masalah menggunakan versi 5.6 atau yang lebih baru. Tidak tahu apakah ini lebih efisien daripada solusi yang sudah bagus (mungkin tidak), tetapi bagi saya itu lebih mudah dibaca:
Menggunakan
strval()
sebagai contoh fungsi dalamarray_map
, ini akan menghasilkan:Semoga saya bukan satu-satunya yang menemukan ini cukup mudah untuk dipahami.
array_combine
menciptakankey => value
array dari array kunci dan array nilai, sisanya cukup jelas.sumber
Anda dapat menggunakan metode peta dari pustaka array ini untuk mencapai apa yang Anda inginkan semudah:
juga mempertahankan kunci dan mengembalikan array baru, belum lagi beberapa mode yang berbeda sesuai dengan kebutuhan Anda.
sumber
Sumber
sumber
Saya selalu suka varian javascript dari array map. Versi paling sederhana adalah:
Jadi sekarang Anda bisa meneruskannya fungsi callback bagaimana membangun nilai-nilai.
sumber
h(g(f($data)))
berlakuf
, lalug
, kemudianh
ke data. Secara umum dianggap lebih serbaguna dalam pemrograman fungsional untuk memiliki fungsi yang melakukan operasi yang sama pada penyelam data, daripada memiliki fungsi yang menerapkan fungsi penyelam ke kumpulan data tetap.Cara lain untuk melakukan ini dengan melestarikan kunci:
sumber
Saya melihat itu kehilangan jawaban yang jelas:
Bekerja persis seperti array_map. Hampir.
Sebenarnya, itu tidak murni
map
seperti yang Anda tahu dari bahasa lain. Php sangat aneh, jadi itu memerlukan beberapa fungsi pengguna yang sangat aneh, karena kami tidak ingin membatalkanworse is better
pendekatan kami yang rusak .Sungguh, sebenarnya tidak
map
sama sekali. Namun, itu masih sangat berguna.Perbedaan pertama yang jelas dari array_map, adalah bahwa callback mengambil output
each()
dari setiap input array bukan hanya nilai. Anda masih dapat melakukan iterasi melalui lebih banyak array sekaligus.Perbedaan kedua adalah cara kunci ditangani setelah dikembalikan dari panggilan balik; nilai balik dari fungsi panggilan balik seharusnya
array('new_key', 'new_value')
. Kunci dapat dan akan diubah, kunci yang sama bahkan dapat menyebabkan nilai sebelumnya ditimpa, jika kunci yang sama dikembalikan. Ini bukanmap
perilaku umum , namun memungkinkan Anda untuk menulis ulang kunci.Hal aneh ketiga adalah, jika Anda menghilangkan
key
nilai balik (baik oleharray(1 => 'value')
atauarray(null, 'value')
), kunci baru akan ditetapkan, seolah-olah$array[] = $value
digunakan. Itu juga bukanmap
perilaku umum, namun terkadang berguna, saya kira.Keanehan keempat adalah, jika fungsi callback tidak mengembalikan nilai, atau mengembalikan
null
, seluruh rangkaian kunci dan nilai saat ini dihilangkan dari output, itu hanya dilewati. Fitur ini benar-benar unmap
py, namun itu akan membuat fungsi ini berfungsi sangat baik untuk gandaarray_filter_assoc
, jika ada fungsi seperti itu.Jika Anda menghilangkan elemen kedua (
1 => ...
) (bagian nilai ) dalam pengembalian panggilan balik,null
digunakan sebagai ganti nilai sebenarnya.Elemen lain apa pun kecuali yang memiliki kunci
0
dan1
sebagai balasannya kembali diabaikan.Dan akhirnya, jika lambda mengembalikan nilai apa pun kecuali
null
atau array, itu diperlakukan seolah-olah kedua kunci dan nilai dihilangkan, jadi:null
digunakan sebagai nilainyaCATATAN:
Tidak seperti di
array_map
, semua parameter non-array yang diteruskan kearray_map_assoc
, dengan pengecualian parameter panggilan balik pertama, secara diam-diam dicor ke array.CONTOH:
// TODO: examples, anyone?
sumber