खोज…


जनरेटर का उपयोग क्यों करें?

जेनरेटर तब उपयोगी होते हैं जब आपको बड़े संग्रह को बाद में पुन: व्यवस्थित करने की आवश्यकता होती है। वे एक वर्ग बनाने के लिए एक सरल विकल्प हैं जो एक Iterator को लागू करता है, जो अक्सर ओवरकिल होता है।

उदाहरण के लिए, नीचे दिए गए फ़ंक्शन पर विचार करें।

function randomNumbers(int $length)
{
    $array = [];
    
    for ($i = 0; $i < $length; $i++) {
        $array[] = mt_rand(1, 10);
    }
    
    return $array;
}

यह सब कार्य करता है एक यादृच्छिक संख्या के साथ भरा है कि एक सरणी उत्पन्न करता है। इसका उपयोग करने के लिए, हम randomNumbers(10) कर सकते हैं, जो हमें 10 यादृच्छिक संख्याओं की एक सरणी देगा। क्या होगा यदि हम एक मिलियन यादृच्छिक संख्याएँ उत्पन्न करना चाहते हैं? randomNumbers(1000000) हमारे लिए है, लेकिन स्मृति की कीमत पर करेंगे। एक सरणी में संग्रहीत एक मिलियन पूर्णांक लगभग 33 मेगाबाइट मेमोरी का उपयोग करता है।

$startMemory = memory_get_usage();

$randomNumbers = randomNumbers(1000000);

echo memory_get_usage() - $startMemory, ' bytes';

यह पूरे एक मिलियन यादृच्छिक संख्याओं के उत्पन्न होने और एक बार में एक के बजाय एक बार वापस आने के कारण है। जनरेटर इस मुद्दे को हल करने का एक आसान तरीका है।

एक जनरेटर का उपयोग करके randomNumbers () को फिर से लिखना

हमारे randomNumbers() फ़ंक्शन को जनरेटर का उपयोग करने के लिए फिर से लिखा जा सकता है।

<?php

function randomNumbers(int $length)
{
    for ($i = 0; $i < $length; $i++) {
        // yield tells the PHP interpreter that this value
        // should be the one used in the current iteration.
        yield mt_rand(1, 10);
    }
}

foreach (randomNumbers(10) as $number) {
    echo "$number\n";
}

जनरेटर का उपयोग करते हुए, हमें फ़ंक्शन से वापस आने के लिए यादृच्छिक संख्याओं की एक पूरी सूची बनाने की ज़रूरत नहीं है, जिसके कारण बहुत कम मेमोरी का उपयोग किया जा रहा है।

एक जनरेटर के साथ एक बड़ी फ़ाइल पढ़ना

जनरेटर के लिए एक सामान्य उपयोग मामला डिस्क से एक फ़ाइल को पढ़ रहा है और इसकी सामग्री पर पुनरावृति करता है। नीचे एक वर्ग है जो आपको CSV फ़ाइल पर पुनरावृति करने की अनुमति देता है। इस स्क्रिप्ट के लिए मेमोरी उपयोग बहुत अनुमानित है, और सीएसवी फ़ाइल के आकार के आधार पर उतार-चढ़ाव नहीं होगा।

<?php

class CsvReader
{
    protected $file;
 
    public function __construct($filePath) {
        $this->file = fopen($filePath, 'r');
    }
 
    public function rows()
    {
        while (!feof($this->file)) {
            $row = fgetcsv($this->file, 4096);
            
            yield $row;
        }
        
        return;
    }
}
 
$csv = new CsvReader('/path/to/huge/csv/file.csv');

foreach ($csv->rows() as $row) {
    // Do something with the CSV row.
}

यील्ड कीवर्ड

एक yield विवरण एक रिटर्न स्टेटमेंट के समान है, सिवाय इसके कि फ़ंक्शन के निष्पादन को रोकने और लौटने के बजाय, उपज जेनरेटर ऑब्जेक्ट देता है और जनरेटर फ़ंक्शन के निष्पादन को रोक देता है।

यहां एक जनरेटर के रूप में लिखित रेंज फ़ंक्शन का एक उदाहरण दिया गया है:

function gen_one_to_three() {
    for ($i = 1; $i <= 3; $i++) {
        // Note that $i is preserved between yields.
        yield $i;
    }
}

आप देख सकते हैं कि यह फ़ंक्शन var_dump के आउटपुट का निरीक्षण करके जेनरेटर ऑब्जेक्ट लौटाता है:

var_dump(gen_one_to_three())

# Outputs:
class Generator (0) {
}

उपज मान रहे हैं

जेनरेटर ऑब्जेक्ट फिर एक सरणी की तरह पुनरावृत्त हो सकता है।

foreach (gen_one_to_three() as $value) {
    echo "$value\n";
}

उपरोक्त उदाहरण आउटपुट होगा:

1
2
3

कुंजी के साथ उपज मान

पैदावार मूल्यों के अलावा, आप कुंजी / मूल्य जोड़े भी प्राप्त कर सकते हैं।

function gen_one_to_three() {
    $keys = ["first", "second", "third"];

    for ($i = 1; $i <= 3; $i++) {
        // Note that $i is preserved between yields.
        yield $keys[$i - 1] => $i;
    }
}

foreach (gen_one_to_three() as $key => $value) {
    echo "$key: $value\n";
}

उपरोक्त उदाहरण आउटपुट होगा:

first: 1
second: 2
third: 3

जनरेटर को मान देने के लिए भेजें () - फ़ंक्शन का उपयोग करना

जनरेटर तेजी से कोडित होते हैं और कई मामलों में भारी चलना-कार्यान्वयन के लिए एक पतला विकल्प होता है। तेजी से क्रियान्वयन से नियंत्रण की थोड़ी कमी आती है जब एक जनरेटर को उत्पादन बंद करना चाहिए या अगर उसे कुछ और उत्पन्न करना चाहिए। हालाँकि, यह प्रत्येक लूप के बाद जनरेटर को पैरामीटर भेजने के लिए अनुरोध फ़ंक्शन को सक्षम करने, send() फ़ंक्शन के उपयोग के साथ प्राप्त किया जा सकता है।

//Imagining accessing a large amount of data from a server, here is the generator for this:
function generateDataFromServerDemo()
{
    $indexCurrentRun = 0; //In this example in place of data from the server, I just send feedback everytime a loop ran through.

    $timeout = false;
    while (!$timeout)
    {
        $timeout = yield $indexCurrentRun; // Values are passed to caller. The next time the generator is called, it will start at this statement. If send() is used, $timeout will take this value.
        $indexCurrentRun++;
    }

    yield 'X of bytes are missing. </br>';
}

// Start using the generator
$generatorDataFromServer = generateDataFromServerDemo ();
foreach($generatorDataFromServer as $numberOfRuns)
{
    if ($numberOfRuns < 10)
    {
        echo $numberOfRuns . "</br>";
    }
    else
    {
        $generatorDataFromServer->send(true); //sending data to the generator
        echo $generatorDataFromServer->current(); //accessing the latest element (hinting how many bytes are still missing.
    }
}

इस आउटपुट में परिणाम:

यहाँ छवि विवरण दर्ज करें



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow