bahay - Setup ng internet
Foreach php value ng mga sumusunod. gawin habang at foreach loop

gawin habang at foreach loop

gawin loop . . habang

gawin...habang umikot sa C# ito ay isang bersyon ng while na may post-condition check. Nangangahulugan ito na ang kondisyon ng loop ay nasuri pagkatapos na maisakatuparan ang katawan ng loop. Samakatuwid, gawin...habang ang mga loop ay kapaki-pakinabang sa mga sitwasyon kung saan ang isang bloke ng mga pahayag ay dapat na maisakatuparan nang hindi bababa sa isang beses. Ang sumusunod ay ang pangkalahatang anyo ng isang do-while loop na pahayag:

gawin (mga operator; ) habang (kondisyon);

Kung mayroon lamang isang operator, ang mga kulot na brace sa ganitong paraan ng notasyon ay opsyonal. Gayunpaman, kadalasang ginagamit ang mga ito upang gawing mas nababasa ang do-while construct at hindi malito sa while loop construct. Gumagana ang do-while loop hangga't totoo ang conditional expression. Ang isang halimbawa ng paggamit ng do-while loop ay ang sumusunod na programa, na kinakalkula ang factorial ng isang numero:

Paggamit ng System; gamit ang System.Collections.Generic; gamit ang System.Linq; gamit ang System.Text; namespace ConsoleApplication1 ( class Program ( static void Main(string args) ( try ( // Kalkulahin ang factorial ng isang numero int i, resulta = 1, num = 1; Console.WriteLine("Enter a number:"); i = int .Parse(Console .ReadLine()); Console.Write("\n\nFactorial (0) = ", i); do ( resulta *= num; num++; ) habang (num

foreach loop

foreach loop nagsisilbi para sa paikot na pag-access sa mga elemento ng isang koleksyon, na isang pangkat ng mga bagay. Tinutukoy ng C# ang ilang uri ng mga koleksyon, bawat isa ay isang array. Ang sumusunod ay ang pangkalahatang anyo ng foreach loop statement:

foreach (uri ng loop_variable_name sa koleksyon) na pahayag;

Dito i-type ang loop_variable_name nagsasaad ng uri at pangalan ng loop control variable na tumatanggap ng halaga ng susunod na elemento ng koleksyon sa bawat hakbang ng foreach loop. At ang koleksyon ay nagsasaad ng isang cyclically query na koleksyon, na pagkatapos nito ay kumakatawan sa isang array. Samakatuwid, ang uri ng loop variable ay dapat tumugma sa uri ng array element. Bilang karagdagan, ang isang uri ay maaaring tukuyin ng var keyword. Sa kasong ito, tinutukoy ng compiler ang uri ng variable ng loop batay sa uri ng elemento ng array. Ito ay maaaring maging kapaki-pakinabang para sa pagtatrabaho sa ilang mga uri ng mga query. Ngunit, bilang panuntunan, ang uri ay tahasang tinukoy.

Ang foreach loop statement ay gumagana tulad ng sumusunod. Kapag nagsimula ang loop, ang unang elemento ng array ay pinili at itinalaga sa loop variable. Sa bawat kasunod na hakbang sa pag-ulit, ang susunod na elemento ng array ay pinili at iniimbak sa isang loop variable. Nagtatapos ang loop kapag napili ang lahat ng elemento ng array.

Binibigyang-daan ka ng foreach loop na umulit sa bawat elemento ng isang koleksyon (isang bagay na kumakatawan sa isang listahan ng iba pang mga bagay). Sa teknikal, para sa isang bagay na maituturing na isang koleksyon, dapat itong suportahan ang IEnumerable interface. Kasama sa mga halimbawa ng mga koleksyon ang mga C# array, mga klase ng koleksyon mula sa System.Collection namespace, at mga custom na klase ng koleksyon.

Ang Para sa Bawat...Susunod na loop sa VBA Excel, ang syntax nito at paglalarawan ng mga indibidwal na bahagi. Mga halimbawa ng paggamit ng For Each...Next loop.

Ang Para sa Bawat... Susunod na loop sa VBA Excel ay idinisenyo upang magsagawa ng isang bloke ng mga pahayag na may kaugnayan sa bawat elemento mula sa isang pangkat ng mga elemento (saklaw, hanay, koleksyon). Ang kahanga-hangang loop na ito ay ginagamit kapag ang bilang ng mga elemento sa isang grupo at ang kanilang pag-index ay hindi alam, kung hindi, mas mainam na gamitin ang .

Para sa Bawat...Next Loop Syntax

Para sa Bawat elemento Sa pangkat [ statements ] [ Exit For ] [ statements ] Next [ element ]

Ang mga square bracket ay nagpapahiwatig ng mga opsyonal na katangian ng For Each...Next loop.

Mga Bahagi ng Para sa Bawat... Susunod na Loop

*Kung ang Para sa Bawat...Susunod na loop ay ginagamit sa VBA Excel upang umulit sa pamamagitan ng mga elemento ng isang koleksyon (Collection object) o array, pagkatapos ay ang variable elemento dapat ideklara na may uri ng data Variant, kung hindi ay hindi gagana ang loop.

**Kung hindi mo ginagamit ang iyong sariling code sa isang loop, mawawala ang kahulugan ng paggamit ng loop.

Mga Halimbawa ng Para sa Bawat...Susunod na mga loop

Mag-loop sa isang hanay ng mga cell

Sa aktibong sheet ng Excel workbook, pumili ng hanay ng mga cell at patakbuhin ang sumusunod na pamamaraan:

Sub test1() Dim element As Range, a As String a = "Data na nakuha ng For Each... Next:" Para sa Bawat elemento Sa Selection a = a & vbNewLine & "Cell " & element.Address & _ " ay naglalaman ng value : " & CStr(element.Value) Susunod na MsgBox isang End Sub

Ipapakita ng window ng impormasyon ng MsgBox ang mga address ng mga napiling cell at ang mga nilalaman nito, kung mayroon man. Kung maraming mga cell ang napili, pagkatapos ay hindi ipapakita ang kumpletong impormasyon sa lahat ng mga cell, dahil ang maximum na haba ng parameter Prompt ay humigit-kumulang 1024 character.

Loop para sa isang koleksyon ng mga sheet

Kopyahin ang sumusunod na pamamaraan ng VBA sa mga workbook ng Excel:

Sub test2() Dim element Bilang Worksheet, a As String a = "Listahan ng mga sheet na nakapaloob sa worksheet na ito:" Para sa Bawat elemento Sa Worksheets a = a & vbNewLine & element.Index _ & ") " & element.Name Next MsgBox a End Sub

Ang window ng impormasyon ng MsgBox ay magpapakita ng isang listahan ng mga pangalan ng lahat ng mga sheet sa Excel workbook sa pamamagitan ng serial number ng kanilang mga label na tumutugma sa kanilang mga index.

Loop para sa isang array

Magtalaga tayo ng listahan ng mga pangalan ng hayop sa array at isulat ang mga ito sa isang variable sa For Each... Next loop a. Ang window ng impormasyon ng MsgBox ay magpapakita ng isang listahan ng mga pangalan ng hayop mula sa variable a.

Sub test3() Dim element As Variant, a As String, group As Variant group = Array("hippopotamus", "elephant", "kangaroo", "tiger", "mouse") "o maaari mong italaga ang mga halaga ng ang hanay ng mga cell ng "manggagawa" sa array sheet, halimbawa, napili: group = Selection a = "Ang array ay naglalaman ng mga sumusunod na value:" & vbNewLine Para sa Bawat elemento Sa grupo a = a & vbNewLine & element Next MsgBox a End Sub

Ulitin natin ang parehong pamamaraan ng VBA, ngunit italaga ang halaga na "Parrot" sa lahat ng elemento ng array sa For Each...Next loop. Ang window ng impormasyon ng MsgBox ay magpapakita ng isang listahan ng mga pangalan ng hayop, na binubuo lamang ng mga parrot, na nagpapatunay na posibleng i-edit ang mga halaga ng mga elemento ng array sa For Each...Next loop.

Sub test4() Dim element As Variant, a As String, group As Variant group = Array("hippopotamus", "elephant", "kangaroo", "tiger", "mouse") "o maaari mong italaga ang mga halaga ng ang hanay ng mga cell ng "manggagawa" sa array sheet, halimbawa, ang napili: group = Selection a = "Ang array ay naglalaman ng mga sumusunod na value:" & vbNewLine Para sa Bawat elemento Sa grupong elemento = "Parrot" a = a & vbNewLine at elemento Susunod na MsgBox isang End Sub

Ang code na ito, tulad ng lahat ng iba sa artikulong ito, ay sinubukan sa Excel 2016.

Umikot sa isang koleksyon ng mga subdirectory at lumabas sa loop

Sa halimbawang ito ay magdaragdag kami sa variable a mga pangalan ng mga subdirectory sa disk C iyong computer. Kapag ang loop ay umabot sa folder Mga File ng Programa, ito ay magdaragdag sa variable a pamagat at mensahe nito: “Enough, I will not read any further! Taos-puso, ang iyong Para sa Bawat...Next cycle."

Sub test5() Dim FSO Bilang Bagay, myFolder Bilang Bagay, myFolder Bilang Bagay, isang Bilang String "Gumawa ng bagong FileSystemObject at italaga ito sa variable na "FSO" Itakda ang FSO = CreateObject("Scripting.FileSystemObject") "Kunin ang listahan ng mga subdirectory sa drive "C" " at italaga "ito sa variable na "myFolders" Itakda ang myFolders = FSO.GetFolder("C:\") a = "Mga folder sa drive C:" & vbNewLine "Nag-loop kami sa listahan ng mga subdirectory at idagdag ang kanilang mga pangalan sa variable na "a" Nang maabot ang folder na "Program Files", lalabas kami sa cycle Para sa Bawat myFolder Sa myFolders.SubFolder a = a & vbNewLine & myFolder.Name Kung myFolder.Name = "Program Files" Then a = a & vbNewLine & vbNewLine & "Tama na, basahin mo na I won't!" _ & vbNewLine & vbNewLine & "Regards," & vbNewLine & _ "Your loop is For Each... Next." Exit For End If Next Set FSO = Walang MsgBox isang End Sub

Ang window ng impormasyon ng MsgBox ay magpapakita ng isang listahan ng mga pangalan ng subdirectory sa disk C iyong computer sa folder Mga File ng Programa inclusive at isang mensahe mula sa cycle tungkol sa pagwawakas ng trabaho nito.

Bilang resulta ng pagpapatakbo ng programa, hindi lamang ang mga pangalan ng mga subdirectory na nakikita kapag nagna-navigate sa disk sa Explorer ang ipapakita. C, ngunit nakatago din at mga folder ng serbisyo. Upang tingnan ang isang listahan ng lahat ng mga subdirectory sa isang disk C, magkomento sa seksyon ng code mula sa Kung dati Tapusin kung kasama at patakbuhin ang pamamaraan sa editor ng VBA Excel.

Kadalasan kailangan mong ulitin ang lahat ng mga elemento ng isang PHP array at magsagawa ng ilang operasyon sa bawat elemento. Halimbawa, maaari mong i-output ang bawat value sa isang HTML table o bigyan ang bawat elemento ng bagong value.

Sa araling ito, titingnan natin ang foreach construct kapag nag-aayos ng loop sa mga naka-index at nauugnay na array.

I-loop ang mga halaga ng elemento

Ang pinakasimpleng kaso ng paggamit para sa foreach ay ang pag-loop sa mga halaga sa isang naka-index na array. Pangunahing syntax:

Foreach ($array as $value) ( ​​​​ // Do something with $value ) // Dito ay ipapatupad ang code pagkatapos makumpleto ang loop

Halimbawa, ang sumusunod na script ay umuulit sa listahan ng mga direktor sa isang naka-index na hanay at nagpi-print ng pangalan ng bawat isa:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); foreach ($director bilang $director) ( echo $director . "
"; }

Ang code sa itaas ay maglalabas ng:

Alfred Hitchcock Stanley Kubrick Martin Scorsese Fritz Lang

Loop ng Key-Value

Paano ang mga nauugnay na array? Kapag gumagamit ng ganitong uri ng array, madalas kailangan mong magkaroon ng access sa susi ng bawat elemento pati na rin ang halaga nito. Ang foreach construct ay may paraan upang malutas ang problema:

Foreach ($array bilang $key => $value) ( ​​// Gawin ang isang bagay gamit ang $key at/o $value ) // Dito ipapatupad ang code pagkatapos makumpleto ang loop

Isang halimbawa ng pag-aayos ng loop sa pamamagitan ng nauugnay na array na may impormasyon tungkol sa mga pelikula, na nagpapakita ng susi ng bawat elemento at ang halaga nito sa HTML na listahan ng mga kahulugan:

$movie = array("title" => "Rear Window", "director" => "Alfred Hitchcock", "year" => 1954, "minutes" => 112); echo"

"; foreach ($pelikula bilang $key => $value) (echo "
$key:
"; echo"
$halaga
"; ) echo "
";

Kapag naisakatuparan, ang script na ito ay maglalabas ng:

Pamagat: Direktor sa Rear Window: Alfred Hitchcock taon: 1954 minuto: 112

Pagbabago ng halaga ng isang elemento

Paano ang tungkol sa pagbabago ng halaga ng isang elemento habang dumadaan ang loop? Maaari mong subukan ang code na ito:

Foreach ($myArray bilang $value) ($value = 123; )

Gayunpaman, kung patakbuhin mo ito, makikita mo na ang mga halaga sa array huwag kang magbago. Ang dahilan ay ang foreach ay gumagana sa isang kopya mga halaga ng array, hindi kasama ang orihinal. Sa ganitong paraan nananatiling buo ang orihinal na hanay.

Upang baguhin ang mga halaga ng array na kailangan mo link sa kahulugan. Para magawa ito, kailangan mong maglagay ng & sign sa harap ng value variable sa foreach construct:

Foreach ($myArray bilang &$value) ($value = 123; )

Halimbawa, ang sumusunod na script ay umiikot sa bawat elemento (pangalan ng direktor) sa $directors array, at ginagamit ang PHP explode() function at ang list construct upang palitan ang una at huling pangalan:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); // Baguhin ang format ng pangalan para sa bawat elemento foreach ($director bilang &$director) ( list($firstName, $lastName) = explode(" ", $director); $director = "$lastName, $firstName"; ) unset ($director); // I-print ang huling resulta foreach ($director bilang $director) ( echo $director . "
"; }

Ang script ay maglalabas ng:

Hitchcock, Alfred Kubrick, Stanley Scorsese, Martin Lang, Fritz

Tandaan na tinatawag ng script ang unset() function upang alisin ang $director variable pagkatapos makumpleto ang unang loop. Ito ay isang magandang kasanayan kung plano mong gamitin ang variable sa ibang pagkakataon sa script sa ibang konteksto.

Kung hindi mo aalisin ang reference, magkakaroon ka ng panganib ng karagdagang pagpapatupad ng code nang hindi sinasadyang sumangguni sa huling elemento sa array ("Lang, Fritz") kung patuloy mong gagamitin ang variable na $director, na hahantong sa mga hindi inaasahang kahihinatnan!

Buod

Sa tutorial na ito, tiningnan namin kung paano gamitin ang PHP foreach construct para i-loop ang mga elemento ng isang array. Ang mga sumusunod na isyu ay isinasaalang-alang:

  • Paano mag-loop sa mga elemento ng array
  • Paano i-access ang susi at halaga ng bawat elemento
  • Paano gumamit ng isang sanggunian upang baguhin ang mga halaga habang dumadaan ka sa isang loop

Sa isang kamakailang digest ng mga kagiliw-giliw na link tungkol sa PHP, nakakita ako ng isang link sa isang komento ni Nikita Popov sa StackOverflow, kung saan siya ay nagsasalita nang detalyado tungkol sa mekanismo "sa ilalim ng hood" ng foreach control construct.
Dahil minsan ay gumagana ang foreach sa higit sa isang maliit na kakaibang paraan, nakita kong kapaki-pakinabang na isalin ang sagot na ito.

Pansin: ipinapalagay ng tekstong ito ang isang pangunahing kaalaman sa functionality ng zvals sa PHP, partikular na dapat mong malaman kung ano ang refcount at is_ref.
gumagana ang foreach sa mga entity na may iba't ibang uri: na may mga array, na may mga simpleng object (kung saan nakalista ang mga available na property) at may Traversable object (o sa halip, mga object na may tinukoy na internal get_iterator handler). Madalas nating pinag-uusapan ang mga arrays dito, ngunit pag-uusapan ko ang iba pa sa pinakadulo.

Bago tayo magsimula, ang ilang mga salita tungkol sa mga array at ang kanilang traversal, mahalaga para sa pag-unawa sa konteksto.

Paano gumagana ang array traversal?

Ang mga array sa PHP ay inayos ng mga hash table (ang mga elemento ng hash ay pinagsama sa isang dobleng naka-link na listahan) at ang foreach ay binabagtas ang array kasunod ng tinukoy na pagkakasunud-sunod.

Kasama sa PHP ang dalawang paraan upang tumawid sa isang array:

  • Ang unang paraan ay isang panloob na array pointer. Ang pointer na ito ay bahagi ng istraktura ng HashTable at isa lang itong pointer sa kasalukuyang elemento ng hash table. Ang panloob na array pointer ay maaaring baguhin nang walang parusa, iyon ay, kung ang kasalukuyang elemento ay tinanggal, ang panloob na array pointer ay ililipat sa susunod.
  • Ang pangalawang mekanismo ng pag-ulit ay isang panlabas na array pointer na tinatawag na HashPosition. Ito ay mahalagang kapareho ng panloob na array pointer, ngunit hindi ito bahagi ng HashTable. Ang panlabas na paraan ng pag-ulit na ito ay hindi ligtas sa pagbabago. Kung aalisin mo ang elementong itinuro ng HashPosition, maiiwan kang may nakabitin na pointer, na magreresulta sa isang segmentation fault.

Kaya, ang mga panlabas na array pointer ay dapat lamang gamitin kapag ikaw ay ganap na sigurado na walang user code na isasagawa sa panahon ng traversal. At ang naturang code ay maaaring mapunta sa mga hindi inaasahang lugar, tulad ng isang tagapangasiwa ng error o isang destructor. Ito ang dahilan kung bakit sa karamihan ng mga kaso ang PHP ay kailangang gumamit ng isang panloob na pointer sa halip na isang panlabas. Kung hindi man, maaaring mag-crash ang PHP sa isang segmentation fault sa sandaling magsimulang gumawa ang user ng anumang bagay na hindi karaniwan.

Ang problema sa panloob na pointer ay bahagi ito ng HashTable. Kaya kapag binago mo ito, ang HashTable ay nagbabago kasama nito. At dahil ang mga arrays sa PHP ay naa-access ayon sa halaga (at hindi sa pamamagitan ng sanggunian), napipilitan kang kopyahin ang array upang mai-loop ang mga elemento nito.

Ang isang simpleng halimbawa na nagpapakita ng kahalagahan ng pagkopya (hindi gaanong karaniwan, sa pamamagitan ng paraan) ay nested iteration:

Foreach ($array bilang $a) ( foreach ($array bilang $b) ( // ... ) )

Dito nais mong ang parehong mga loop ay independyente, at hindi matalinong itinapon sa isang pointer.

Kaya dumating kami sa foreach.

Ang pagtawid sa isang array sa foreach

Ngayon alam mo na kung bakit kailangang gumawa ng kopya ng array si foreach bago ito lampasan. Ngunit malinaw na hindi ito ang buong kuwento. Kung ang PHP ay gumagawa ng isang kopya o hindi ay depende sa ilang mga kadahilanan:

  • Kung ang iterable array ay isang reference, walang pagkopya na magaganap, sa halip ay ipapatupad ang addref:

    $ref =& $array; // $array has is_ref=1 now foreach ($array as $val) ( // ... )
    Bakit? Dahil ang anumang pagbabago sa array ay dapat na ipalaganap sa pamamagitan ng sanggunian, kasama ang panloob na pointer. Kung gumawa ng kopya si foreach sa kasong ito, masisira nito ang semantika ng link.

  • Kung ang array ay may refcount=1, ang pagkopya ay hindi na isasagawa muli. refcount=1 ay nangangahulugan na ang array ay hindi ginagamit sa ibang lugar at foreach ay maaaring gamitin ito nang direkta. Kung mas malaki sa isa ang refcount, ibinabahagi ang array sa iba pang mga variable at para maiwasan ang pagbabago, dapat itong kopyahin ng foreach (anuman ang reference case na inilarawan sa itaas).
  • Kung ang array ay reference-traversed (foreach ($array as &$ref)), kung gayon - anuman ang copy o non-copy function - ang array ay magiging reference.

Kaya ito ang unang bahagi ng misteryo: ang function ng kopya. Ang pangalawang bahagi ay kung paano isinasagawa ang kasalukuyang pag-ulit, at medyo kakaiba din ito. Ang "normal" na pattern ng pag-ulit na alam mo na (at kadalasang ginagamit sa PHP - hiwalay sa foreach) ay ganito ang hitsura (pseudocode):

I-reset(); habang (get_current_data(&data) == SUCCESS) ( code(); move_forward(); )
ang foreach na pag-ulit ay mukhang medyo naiiba:

I-reset(); habang (get_current_data(&data) == SUCCESS) ( move_forward(); code(); )

Ang pagkakaiba ay ang move_forward() ay isinasagawa sa simula sa halip na sa dulo ng loop. Kaya, kapag gumagamit ang user code ng elementong $i, ang panloob na array pointer ay tumuturo na sa elementong $i+1.

Ang mode na ito ng pagpapatakbo ng foreach ay din ang dahilan kung bakit ang panloob na array pointer ay lumilipat sa susunod na elemento kung ang kasalukuyang isa ay tinanggal, sa halip na sa nauna (tulad ng maaari mong asahan). Ang lahat ay idinisenyo upang gumana nang mahusay sa foreach (ngunit malinaw na hindi gagana nang maayos sa lahat ng iba pa, laktawan ang mga elemento).

Mga implikasyon ng code

Ang unang kinahinatnan ng pag-uugali sa itaas ay ang foreach ay kinokopya ang iterable array sa maraming mga kaso (mabagal). Ngunit huwag matakot: Sinubukan kong tanggalin ang kinakailangan sa pagkopya at wala akong makitang anumang speedup kahit saan maliban sa mga artipisyal na benchmark (na umulit nang dalawang beses sa bilis). Parang hindi sapat ang pag-ulit ng mga tao.

Ang pangalawang kahihinatnan ay karaniwang walang ibang kahihinatnan. Ang pag-uugali ng foreach sa pangkalahatan ay lubos na nauunawaan ng gumagamit at gumagana lamang ayon sa nararapat. Hindi mo dapat pakialam kung paano nangyayari ang pagkopya (o kung nangyari man ito), o sa anong partikular na punto ng oras na inilipat ang pointer.

At ang pangatlong kahihinatnan - at dito tayo dumarating sa iyong problema - kung minsan ay nakikita natin ang kakaibang pag-uugali na mahirap maunawaan. Ito ay partikular na nangyayari kapag sinubukan mong baguhin ang array mismo, na iyong tinatahak sa isang loop.

Ang isang malaking koleksyon ng pag-uugali ng edge case na nangyayari kapag binago mo ang isang array sa panahon ng pag-ulit ay makikita sa mga pagsubok sa PHP. Maaari kang magsimula sa pagsusulit na ito, pagkatapos ay baguhin ang 012 sa 013 sa address, at iba pa. Makikita mo kung paano magpapakita ang bawat pag-uugali sa iba't ibang sitwasyon (lahat ng uri ng kumbinasyon ng mga link, atbp.).

Ngayon bumalik tayo sa iyong mga halimbawa:

Foreach ($array bilang $item) ( echo "$item\n"; $array = $item; ) print_r($array); /* Output sa loop: 1 2 3 4 5 $array pagkatapos ng loop: 1 2 3 4 5 1 2 3 4 5 */

Narito ang $array ay mayroong refcount=1 bago ang loop upang hindi ito makopya ngunit makakakuha ng addref. Sa sandaling magtalaga ka ng halaga sa $array, mahahati ang zval, kaya ang array na dinadagdagan mo ng mga elemento at ang array na inuulit mo ay magiging dalawang magkaibang array.

Foreach ($array bilang $key => $item) ($array[$key + 1] = $item + 2; echo "$item\n"; ) print_r($array); /* Output sa loop: 1 2 3 4 5 $array pagkatapos ng loop: 1 3 4 5 6 7 */

Ang parehong sitwasyon tulad ng sa unang pagsubok.

// Shift the pointer by one to make sure na hindi ito makakaapekto sa foreach var_dump(each($array)); foreach ($array bilang $item) ( echo "$item\n"; ) var_dump(each($array)); /* Output array(4) ( => int(1) ["value"]=> int(1) => int(0) ["key"]=> int(0) ) 1 2 3 4 5 bool( mali) */

Same story ulit. Sa panahon ng foreach loop, mayroon kang refcount=1 at makakakuha ka lamang ng addref, mababago ang panloob na $array pointer. Sa dulo ng loop, ang pointer ay nagiging NULL (ito ay nangangahulugan na ang pag-ulit ay nakumpleto). bawat isa ay nagpapakita nito sa pamamagitan ng pagbabalik ng mali.

Foreach ($array bilang $key => $item) ( echo "$item\n"; each($array); ) /* Output: 1 2 3 4 5 */

Foreach ($array bilang $key => $item) ( echo "$item\n"; reset ($array); ) /* Output: 1 2 3 4 5 */

Ngunit ang mga halimbawang ito ay hindi sapat na nakakumbinsi. Nagsisimulang maging talagang hindi mahulaan ang pag-uugali kapag gumamit ka ng kasalukuyang sa isang loop:

Foreach ($array bilang $val) ( var_dump(current($array)); ) /* Output: 2 2 2 2 2 */

Dito dapat mong tandaan na ang kasalukuyang ay ina-access din sa pamamagitan ng sanggunian, sa kabila ng hindi pagbabago ng array. Ito ay kinakailangan upang gumana nang pare-pareho sa lahat ng iba pang mga function, tulad ng susunod, ang pag-access sa pamamagitan ng reference (kasalukuyan ay talagang isang mas kanais-nais na function ng ref; maaari itong makakuha ng isang halaga, ngunit gumagamit ng isang reference kung maaari). Ang isang sanggunian ay nangangahulugan na ang array ay dapat na ihiwalay, kaya ang $array at ang kopya ng $array na ginagamit ng bawat isa ay magiging independyente. Kung bakit ka nakakuha ng 2 at hindi 1 ay binanggit din sa itaas: foreach increments array pointer bago magsimula ang user code, hindi pagkatapos. Kaya kahit na gumagana pa rin ang code sa unang elemento, inilipat na ng foreach ang pointer sa pangalawa.

Ngayon subukan natin ang isang maliit na pagbabago:

$ref = &$array; foreach ($array bilang $val) ( var_dump(current($array)); ) /* Output: 2 3 4 5 false */

Narito mayroon kaming is_ref=1, kaya ang array ay hindi kinopya (katulad ng nasa itaas). Ngunit ngayon na mayroong is_ref, ang array ay hindi na kailangang hatiin, na ipinapasa sa pamamagitan ng pagtukoy sa kasalukuyang. Ngayon gumagana ang kasalukuyan at foreach sa parehong array. Nakikita mo ang array na inilipat ng isa nang tumpak dahil sa paraan ng pagtrato ng foreach sa pointer.

Makikita mo ang parehong bagay kapag binagtas mo ang isang array sa pamamagitan ng sanggunian:

Foreach ($array as &$val) ( var_dump(current($array)); ) /* Output: 2 3 4 5 false */

Ang mahalagang bagay dito ay ang foreach ay magtatalaga ng aming $array is_ref=1 kapag ito ay nag-loop sa ibabaw nito sa pamamagitan ng sanggunian, kaya ito ay magiging pareho sa itaas.

Isa pang maliit na variation, dito namin itatalaga ang aming array sa isa pang variable:

$foo = $array; foreach ($array as $val) ( var_dump(current($array)); ) /* Output: 1 1 1 1 1 */

Dito ang refcount ng $array ay nakatakda sa 2 kapag nagsimula ang loop, kaya kailangang gumawa ng kopya bago magsimula. Kaya ang $array at ang array na ginamit ng foreach ay mag-iiba mula sa simula. Iyon ang dahilan kung bakit nakukuha mo ang posisyon ng panloob na array pointer na may kaugnayan bago magsimula ang loop (sa kasong ito ito ay nasa unang posisyon).

Pag-ulit ng mga bagay

Kapag inuulit ang mga bagay, makatuwirang isaalang-alang ang dalawang kaso:

Ang bagay ay hindi Traversable (o sa halip, ang panloob na get_iterator handler ay hindi tinukoy)

Sa kasong ito, ang pag-ulit ay nangyayari halos kapareho ng sa mga array. Ang parehong semantika ng pagkopya. Ang pagkakaiba lang ay tatakbo ang foreach ng ilang karagdagang code para laktawan ang mga property na hindi available sa kasalukuyang saklaw. Ang ilang mas kawili-wiling mga katotohanan:

  • Para sa mga ipinahayag na katangian, muling ino-optimize ng PHP ang talahanayan ng hash ng property. Kung inuulit mo ang bagay, dapat itong muling buuin ang hash table na iyon (na nagpapataas ng paggamit ng memorya). Hindi sa dapat kang mag-alala tungkol dito, maging aware ka lang.
  • Sa bawat pag-ulit, muling makukuha ang talahanayan ng hash ng property, ibig sabihin, tatawagan ng PHP ang get_properties nang paulit-ulit. Para sa mga "regular" na pag-aari na ito ay hindi napakahalaga, ngunit kung ang mga katangian ay dynamic na nilikha (ito ay madalas na ginagawa ng mga built-in na klase) pagkatapos ay ang talahanayan ng ari-arian ay muling kakalkulahin sa bawat oras.
Madadaanan na bagay

Sa kasong ito, ang lahat ng sinabi sa itaas ay hindi mailalapat sa anumang paraan. Gayundin, hindi kokopya ang PHP at hindi gagamit ng anumang mga trick tulad ng mga pagtaas ng pointer bago mag-loop. Sa tingin ko, ang paraan ng pagdaan sa isang Traversable object ay mas predictable at hindi nangangailangan ng karagdagang paglalarawan.

Pagpapalit ng isang iterable sa panahon ng isang loop

Ang isa pang hindi pangkaraniwang kaso na hindi ko nabanggit ay ang PHP ay nagbibigay-daan sa kakayahang palitan ang isang iterable sa panahon ng isang loop. Maaari kang magsimula sa isang array at magpatuloy sa pamamagitan ng pagpapalit nito ng isa pa sa kalahati. O magsimula sa isang array, pagkatapos ay palitan ito ng isang bagay:

$arr = ; $obj = (bagay); $ref =& $arr; foreach ($ref bilang $val) ( echo "$val\n"; if ($val == 3) ($ref = $obj; ) ) /* Output: 1 2 3 6 7 8 9 10 */

Gaya ng nakikita mo, nagsimula lang ang PHP sa pagtawid sa ibang entity sa sandaling naganap ang pagpapalit.

Pagbabago ng panloob na array pointer sa panahon ng pag-ulit

Isang huling detalye ng foreach na pag-uugali na hindi ko binanggit (dahil maaari itong magamit upang makakuha ng kakaiba talaga ang ugali): ano ang maaaring mangyari kung susubukan mong baguhin ang panloob na array pointer sa panahon ng isang loop.

Dito maaaring hindi mo makuha ang iyong inaasahan: kung tumawag ka sa susunod o nauna sa katawan ng loop (sa kaso ng pagpasa sa pamamagitan ng sanggunian), makikita mo na ang panloob na pointer ay lumipat, ngunit ito ay walang epekto sa pag-uugali ng ang iterator. Ang dahilan ay ang foreach ay gumagawa ng backup ng kasalukuyang posisyon at hash ng kasalukuyang elemento sa HashPointer pagkatapos ng bawat pass ng loop. Sa susunod na pass, susuriin ng foreach kung nagbago ang posisyon ng internal pointer at subukang ibalik ito gamit ang hash na ito.

Tingnan natin kung ano ang ibig sabihin ng "susubukan". Ipinapakita ng unang halimbawa kung paano hindi binabago ng pagbabago ng panloob na pointer ang foreach mode:

$array = ; $ref =& $array; foreach ($array bilang $value) ( ​​​​var_dump($value); reset ($array); ) // output: 1, 2, 3, 4, 5

Ngayon subukan nating i-unset ang elemento na maa-access ng foreach sa unang pass (key 1):

$array = ; $ref =& $array; foreach ($array bilang $value) ( ​​​​var_dump($value); unset($array); reset($array); ) // output: 1, 1, 3, 4, 5

Dito makikita mo na ang counter ay na-reset dahil ang isang elemento na may katugmang hash ay hindi mahanap.

Tandaan, ang hash ay hash lang. Nangyayari ang mga banggaan. Subukan natin ito ngayon:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $array; foreach ($array bilang $value) ( ​​​​unset ($array["EzFY"]); $array["FYFZ"] = 4; reset ($array); var_dump($value); ) // output: 1 1 3 4

Gumagana tulad ng inaasahan namin. Inalis namin ang EzFY key (ang isa kung saan matatagpuan ang foreach), kaya ginawa ang isang pag-reset. Nagdagdag din kami ng dagdag na susi, kaya nakikita namin ang 4 sa dulo.

At narito ang hindi alam. Ano ang mangyayari kung papalitan mo ang FYFY key ng FYFZ? Subukan Natin:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $array; foreach ($array bilang $value) ( ​​​​unset ($array["EzFY"]); $array["FYFY"] = 4; reset ($array); var_dump($value); ) // output: 1 4

Ngayon ang loop ay direktang lumipat sa bagong elemento, nilaktawan ang lahat ng iba pa. Ito ay dahil ang FYFY key ay may banggaan sa EzFY (sa totoo lang, lahat ng mga key mula sa array na ito ay masyadong). Bukod dito, ang elemento ng FYFY ay matatagpuan sa parehong address ng memorya ng elementong EzFY na kakatanggal lang. Kaya para sa PHP ito ay magiging parehong posisyon na may parehong hash. Ang posisyon ay "ibinalik" at ang paglipat sa dulo ng array ay nangyayari.

Ang foreach construct ay isang variation ng para na kasama sa wika upang gawing mas madali ang pag-ulit sa mga elemento ng isang array. Mayroong dalawang bersyon ng foreach command, na idinisenyo para sa iba't ibang uri ng array:

foreach (array bilang $element) (

foreach (array bilang $key => $element) (

Halimbawa, kapag isinasagawa ang sumusunod na snippet:

$menu = аrrау("pasta", "steak", "patatas", "isda", "fries");

foreach ($menu bilang $item) (

i-print ang "$item
";

ang sumusunod na resulta ay magiging output:

Mayroong dalawang bagay na dapat tandaan sa halimbawang ito. Una, ang foreach construct ay awtomatikong bumabalik sa simula ng array (hindi ito nangyayari sa iba pang mga looping construct). Pangalawa, hindi na kailangang tahasang dagdagan ang counter o kung hindi man ay lumipat sa susunod na elemento ng array - awtomatiko itong nangyayari sa bawat pag-ulit ng foreach.

Ang pangalawang opsyon ay ginagamit kapag nagtatrabaho sa mga associative array:

$wine_inventory = array (

"merlot" => 15,

"zinfandel" => 17,

"sauvignon" => 32

foreach ($wine_inventory bilang $i => $item_count) (

print "$item_count bote ng $i na natitira
";

Sa kasong ito, ang resulta ay ganito:

15 bote ng merlot ang natitira

17 bote ng zinfandel ang natitira

32 bote ng sauvignon ang natitira

Tulad ng makikita mo mula sa mga halimbawa sa itaas, ang foreach construct ay makabuluhang pinapasimple ang pagtatrabaho sa mga array.

Ang prinsipyo ng pagpapatakbo ng switch construct ay medyo nakapagpapaalaala ng kung - ang resulta na nakuha mula sa pagsusuri ng expression ay nasuri laban sa isang listahan ng mga potensyal na tugma.

Ito ay lalong kapaki-pakinabang kapag sinusuri ang maraming mga halaga, dahil ang paggamit ng switch ay ginagawang mas visual at compact ang program. Ang pangkalahatang format ng switch command ay:

switch (expression) (

kaso (kondisyon):

kaso (kondisyon):

Ang kundisyong sinusuri ay ipinahiwatig sa mga panaklong pagkatapos ng switch na keyword. Ang resulta ng pagkalkula nito ay sunud-sunod na inihambing sa mga kondisyon sa mga seksyon ng kaso. Kung may nakitang tugma, ang block ng kaukulang seksyon ay isasagawa. Kung walang nakitang tugma, ang opsyonal na default na bloke ng seksyon ay isasagawa.

Tulad ng makikita mo sa mga susunod na kabanata, ang isa sa pinakamalakas na lakas ng PHP ay ang paghawak nito sa input ng user. Sabihin nating ang isang programa ay nagpapakita ng isang drop-down na listahan na may ilang mga opsyon, at ang bawat linya sa listahan ay tumutugma sa isang command na isinasagawa sa isang hiwalay na case construct. Ito ay napaka-maginhawa upang bumuo ng pagpapatupad gamit ang switch command:

$user_input = "mga recipe"; // Utos na pinili ng user

switch ($user_input):

case("paghahanap") :

i-print ang "Magsagawa tayo ng paghahanap!";

case("diksyonaryo") :

print "Anong salita ang gusto mong hanapin?";

case("mga recipe") :

print "Narito ang isang listahan ng mga recipe...";

print "Narito ang menu...";

Tulad ng nakikita mo mula sa fragment sa itaas, ang switch command ay nagbibigay ng malinaw at visual na organisasyon ng code. Ang variable na tinukoy sa kundisyon ng switch (sa halimbawang ito, $user_input) ay inihambing sa mga kundisyon ng lahat ng kasunod na seksyon ng kaso. Kung ang halaga na tinukoy sa seksyon ng kaso ay tumutugma sa halaga ng variable na inihahambing, ang bloke ng seksyong ito ay isasagawa. Pinipigilan ng break na command ang karagdagang mga seksyon ng case na masuri at tinatapos ang pagpapatupad ng switch construct. Kung wala sa mga naka-check na kundisyon ang natutugunan, ang opsyonal na default na seksyon ay isaaktibo. Kung walang default na seksyon at wala sa mga kundisyon ay totoo, ang switch command ay magtatapos lamang at ang pagpapatupad ng programa ay magpapatuloy sa susunod na command.

Dapat mong tandaan na kung walang break command sa case section (tingnan ang susunod na seksyon), magpapatuloy ang execution ng switch sa susunod na command hanggang sa magkaroon ng break command o maabot ang dulo ng switch statement. Ang sumusunod na halimbawa ay nagpapakita ng mga kahihinatnan ng nawawalang break command: $value = 0.4;

switch($value):

print "ang halaga ay 0.4
";

print "ang halaga ay 0.6
";

print "ang halaga ay 0.3
";

print "Hindi ka pumili ng isang halaga!";

Ang resulta ay ganito:

Ang kawalan ng break command ay nagresulta sa pagpapatupad ng hindi lamang print command sa seksyon kung saan natagpuan ang tugma, kundi pati na rin ang print command sa susunod na seksyon. Pagkatapos ang mga utos sa switch statement ay nagambala ng isang switch command kasunod ng pangalawang print command.

Ang pagpili sa pagitan ng switch at kung ang mga utos ay halos walang epekto sa pagganap ng programa. Ang desisyon na gumamit ng isang disenyo o iba ay sa halip ay isang personal na bagay para sa programmer.

Agad na sinira ng break na command ang pagpapatupad ng while, for, o switch statement kung saan ito matatagpuan. Ang utos na ito ay nabanggit na sa nakaraang seksyon, ngunit ang pagkagambala sa kasalukuyang loop ay hindi nauubos ang mga kakayahan ng utos ng break. Sa pangkalahatan, ganito ang hitsura ng break syntax:

Ang opsyonal na parameter n ay tumutukoy sa bilang ng mga antas ng control construct na tinapos ng break command. Halimbawa, kung ang isang break na command ay naka-nest sa loob ng dalawa habang ang mga command at ang break ay sinusundan ng numero 2, ang parehong mga loop ay lalabas kaagad. Ang default na halaga para sa n ay 1; ang paglabas sa isang antas ay maaaring ipahiwatig alinman sa pamamagitan ng tahasang pagtukoy ng 1 o sa pamamagitan ng pagtukoy ng break command na walang parameter. Tandaan na ang i f command ay hindi isa sa mga control construct na maaaring maputol ng break command.



 


Basahin:



Superposition ng Logic Algebra Functions Monotonic Boolean Functions

Superposition ng Logic Algebra Functions Monotonic Boolean Functions

Ang pagsusulatan G sa pagitan ng set A at B ay tinatawag na subset. Kung , kung gayon ang b ay sinasabing tumutugma sa a. Marami sa lahat ng may kaugnayan...

Ano ang isang sistema ng impormasyon?

Ano ang isang sistema ng impormasyon?

Mga portal ng estado, mga website ng ESIA. Pinag-isang sistema ng pagkakakilanlan at pagpapatunay - esia.gosuslugi.ru EPGU. Pinag-isang portal ng mga pampublikong serbisyo...

Paglipat mula sa isang lohikal na pagpapahayag sa isang lohikal na circuit at vice versa

Paglipat mula sa isang lohikal na pagpapahayag sa isang lohikal na circuit at vice versa

Laboratory work No. 4. Pagpapatupad ng circuit ng mga lohikal na elemento. Konstruksyon ng mga lohikal na circuit. Teoretikal na bahagi. Ang pagproseso ay batay sa...

Nizhny Novgorod kahihiyan ng Russian Post

Nizhny Novgorod kahihiyan ng Russian Post

Matapos ang pagpapakilala ng bagong operating system ng EAS OPS, na nagkakahalaga ng 890 milyong rubles, oras ng serbisyo sa customer sa mga post office sa rehiyon...

feed-image RSS