Peta array php dengan kunci

Ketika kita berbicara tentang array, biasanya yang kita maksud adalah vektor dari sesuatu – primitif, objek, atau bahkan array. Tetapi ada banyak situasi ketika kita perlu membawa informasi tambahan dengan data kita. Kita dapat menggunakan array bersarang tetapi tidak menyebabkan item spesifik dalam array akan mudah diidentifikasi. Untuk mencapainya kita harus menggunakan kunci khusus. Mereka menyediakan akses mudah ke setiap elemen array selama kita mengetahui kunci yang sesuai dengan nilai tersebut

Ada beberapa alasan mengapa kita dapat menggunakan array asosiatif daripada vektor sederhana, mis. g. keterbacaan. Kunci bernama juga lebih bermakna daripada indeks numerik. Alih-alih memikirkan mengapa, bayangkan situasi saat kita bisa menggunakan peta hash. Mari fokus pada bagaimana kita dapat membangun array asosiatif dari sebuah vektor

Contoh skenario

Dalam aplikasi kami, kami memiliki pengguna dari berbagai belahan dunia. Selama proses pendaftaran, pengguna dapat memilih negaranya sendiri. Dalam database kami, kami menyimpan informasi tentang negara dalam format ISO-3361-alpha-1. Pengguna seharusnya melihat nama lengkap negara sebagai gantinya

Kami sebenarnya memiliki array Country objek, yang definisinya disajikan di bawah ini

class Country
{
    private $name;
    private $code;

    public function __construct[string $name, string $code]
    {
        $this->name = $name;   
        $this->code = $code;
    }
    
    public function getName[]: string
    {
        return $this->name;
    }
    
    public function getCode[]: string
    {
        return $this->code;
    }
}

Salah satu komponen frontend kami dapat merender Combo [dikenal sebagai  node] dan mengharapkan array asosiatif sebagai input dalam format ['value' => 'text visible for user']

Kita perlu membuat array ini

Pendekatan #0. lingkaran dasar

function prepareCountriesForCombo[array $countries]: array
{
    $output = [];

    foreach [$countries as $country] {
        $output[$country->getCode[]] = $country->getName[];
    }
    
    return $output;
}

$countriesSelect = prepareCountriesForCombo[$countries];
_

Pendekatan paling dasar yang saya tahu. Saya sering mempertanyakan solusi yang menggunakan loop mentah karena mereka adalah makhluk level rendah. Tetapi jika mereka dikemas dalam fungsi yang dijelaskan dengan baik, itu adalah O. K

Membuat fungsi yang dirancang untuk menghasilkan data spesifik untuk komponen lain tampaknya merupakan ide yang bagus. Mari pertimbangkan bahwa kita perlu mengirim data ke Combo yang berbeda. Alangkah baiknya menggunakan fungsi yang sama tetapi dengan data yang berbeda. Saya perlu menggeneralisasi pendekatan ini

Pendekatan #1. Cara generik untuk menghasilkan array asosiatif

Selain array yang berisi data, kita perlu melewatkan dua fungsi tambahan. Yang pertama akan bertanggung jawab untuk mengubah elemen menjadi teks yang terlihat oleh pengguna dan yang terakhir akan mengubah elemen menjadi kunci peta asosiatif

Fungsinya bisa terlihat seperti ini

function mapForCombo[array $array, Closure $fnValue, Closure $fnKey]: array
{
    $output = [];

    foreach [$array as $element] {
        $output[$fnKey[$element]] = $fnValue[$element];
    }
    
    return $output;
}

$countriesSelect = mapForCombo[
	$countries, 
  	function [Country $country] { return $country->getCode[]; }, 
  	function [Country $country] { return $country->getName[]; }
];

Kelihatannya cukup bagus dan mungkin kita harus berhenti membahas lebih lanjut tentang fitur yang membosankan ini. Lagi pula, mari kita coba mencari implementasi lain untuk kasus khusus ini

Pendekatan #2. menggunakan fungsi peta array

Saya sangat suka fungsi array. Mereka sangat kuat. Kita dapat mengubah kunci dan nilai dari array asosiatif secara mandiri dan kita dapat menggabungkannya menjadi satu array

function mapForCombo[array $array, Closure $fnValue, Closure $fnKey]: array
{
    $keys = array_map[$fnKey, $array];
    $values = array_map[$fnValue, $array];

    return array_combine[$keys, $values];
}

$countriesSelect = mapForCombo[
    $countries, 
    function [Country $country] { return $country->getCode[]; }, 
    function [Country $country] { return $country->getName[]; }
];

Kodenya jauh lebih pendek, tetapi di balik terpal, PHP memiliki lebih banyak pekerjaan. Meskipun tidak ada loop yang terlihat di userland, mesin PHP harus mengulang array setidaknya 3 kali [dua kali untuk peta dan sekali untuk digabungkan]. Tampaknya lambat dan tidak begitu efisien

Pendekatan 3. peta array dengan mengurangi

Pendekatan berikutnya mungkin menggunakan fungsi 

function prepareCountriesForCombo[array $countries]: array
{
    $output = [];

    foreach [$countries as $country] {
        $output[$country->getCode[]] = $country->getName[];
    }
    
    return $output;
}

$countriesSelect = prepareCountriesForCombo[$countries];
_1, bukan pemetaan. Apa fungsi ini sebenarnya saya jelaskan di salah satu posting saya sebelumnya. Sederhananya, pendekatan ini adalah untuk mengurangi array menjadi nilai tunggal. Tapi tidak ada yang mengatakan bahwa nilai tunggal tidak bisa berupa array

function mapForCombo[array $array, Closure $fnValue, Closure $fnKey]: array
{
    return array_reduce[$array, function [$acc, $element] use [$fnKey, $fnValue] {
        $acc[$fnKey[$element]] = $fnValue[$element];
        return $acc;
    }, []];
}

$countriesSelect = mapForCombo[
    $countries, 
    function [Country $country] { return $country->getCode[]; }, 
    function [Country $country] { return $country->getName[]; }
];

Satu-satunya hal yang harus kita lakukan adalah membuat fungsi yang akan menetapkan nilai yang diubah ke kunci tertentu dalam array [mirip dengan pendekatan pertama]. Logika loop disembunyikan di dalam fungsi

function prepareCountriesForCombo[array $countries]: array
{
    $output = [];

    foreach [$countries as $country] {
        $output[$country->getCode[]] = $country->getName[];
    }
    
    return $output;
}

$countriesSelect = prepareCountriesForCombo[$countries];
_1 jadi hanya peduli dengan penugasan yang benar

Solusi mana yang lebih baik?

Tes

Secara pribadi, saya tidak suka melakukan dan membaca tolok ukur untuk hal-hal yang biasanya tidak penting. Kalau tidak, saya mengumpulkan beberapa ide dan saya ingin memvalidasinya sedemikian rupa. Itu sebabnya saya menguji implementasi mana yang bekerja lebih cepat

Uji file dan lingkungan

Saya menyiapkan file pengujian sederhana, Anda dapat melihatnya di GitHub Gist ini. Meskipun tidak begitu rumit, cukup melihat implementasi mana yang lebih baik, relatif satu sama lain. Singkatnya – saya menjalankan setiap fungsi 5000 kali dan saya mengukur durasi eksekusi

Pertama saya mencoba menjalankan skrip ini di lingkungan lokal saya, tetapi saya sampai pada kesimpulan, bahwa opsi bettser adalah menggunakan server yang sama sekali berbeda. Saya menyewa droplet 2GB RAM / 2 CPU dari DigitalOcean yang siap pakai LAMP Stack on board dan saya menjalankan tes

root@lamp-2gb-nyc3-01:~# php -v
PHP 7.0.22-0ubuntu0.16.04.1 [cli] [ NTS ]

Tes menghasilkan output yang saya salin dan tempel sebagai CSV ke Excel. Ini memungkinkan saya untuk dengan mudah menghitung waktu rata-rata dan memplot bagan sederhana

Hasil tes

Harus saya akui, hasil itu sangat mengejutkan saya. Pertama, silakan lihat hasil akhirnya

  • Pendekatan #1 –
    function prepareCountriesForCombo[array $countries]: array
    {
        $output = [];
    
        foreach [$countries as $country] {
            $output[$country->getCode[]] = $country->getName[];
        }
        
        return $output;
    }
    
    $countriesSelect = prepareCountriesForCombo[$countries];
    
    _3 – 0,283 detik
  • Pendekatan #2 –
    function prepareCountriesForCombo[array $countries]: array
    {
        $output = [];
    
        foreach [$countries as $country] {
            $output[$country->getCode[]] = $country->getName[];
        }
        
        return $output;
    }
    
    $countriesSelect = prepareCountriesForCombo[$countries];
    
    _4 – 0,253 detik
  • Pendekatan #3 –
    function prepareCountriesForCombo[array $countries]: array
    {
        $output = [];
    
        foreach [$countries as $country] {
            $output[$country->getCode[]] = $country->getName[];
        }
        
        return $output;
    }
    
    $countriesSelect = prepareCountriesForCombo[$countries];
    
    _1 – 1.054 detik

Perbedaan lebih terlihat pada diagram batang sederhana

Bagan menyajikan durasi rata-rata dari setiap pendekatan

Kesan pertama saya adalah seperti campuran kebingungan dengan kesalahpahaman. Solusi yang tampaknya menjadi yang terbaik ternyata, yang paling tidak efisien. Ini menunjukkan, bahwa kita harus selalu menguji dan memvalidasi ide kita

Saya pribadi cukup sering menggunakan pendekatan

function prepareCountriesForCombo[array $countries]: array
{
    $output = [];

    foreach [$countries as $country] {
        $output[$country->getCode[]] = $country->getName[];
    }
    
    return $output;
}

$countriesSelect = prepareCountriesForCombo[$countries];
1. Untungnya, tes tersebut sengaja dilebih-lebihkan untuk menunjukkan perbedaan antara masing-masing pendekatan. Untuk kumpulan data yang lebih kecil, perbedaannya tidak terlihat

Itu tidak berarti, bahwa Anda tidak boleh menggunakan fungsi

function prepareCountriesForCombo[array $countries]: array
{
    $output = [];

    foreach [$countries as $country] {
        $output[$country->getCode[]] = $country->getName[];
    }
    
    return $output;
}

$countriesSelect = prepareCountriesForCombo[$countries];
1. Ini memiliki kasus dan makna penggunaan khusus jadi jangan ragu untuk menggunakan fungsi ini jika memenuhi kebutuhan Anda

Ringkasan

Saya tidak yakin, apakah eksperimen ini akan mengubah cara saya menulis kode. Sejujurnya, ini hanya optimasi mikro dalam skala yang lebih besar. Meskipun terkadang itu penting, e. g. jika Anda harus menulis algoritme dengan efisiensi tinggi, bagi kebanyakan dari kita itu hanya masalah yang tidak perlu

Kalau tidak, itu mengungkapkan sesuatu yang sama sekali berbeda. Kami percaya bahwa hal-hal bekerja lebih cepat karena tampaknya menjadi lebih cepat. Mereka mengeksekusi lebih sedikit loop dan mengandung logika dan kondisi yang jauh lebih rumit. Contoh ini menunjukkan bahwa tidak ada kebenaran dalam semua kasus

Seperti yang Anda perhatikan, tidak ada aturan emas tentang cara mengubah data ke array asosiatif. Kesederhanaan adalah kuncinya, tetapi kita harus selalu menguji, mengonfirmasi, dan membandingkan solusi kita dengan yang lain. Ini bukan hanya tentang transformasi array tetapi juga tentang banyak hal lainnya. Mungkin solusi Anda berikutnya akan lebih baik, lebih mudah, dan lebih cepat?

Bài mới nhất

Chủ Đề