Prijeđi na sadržaj

Foreach petlja

Izvor: Wikipedija
(Preusmjereno sa stranice Forič petlja)
For each petlje se najčešće koriste da ponove stavke u nizu elemenata .

U računarskom programiranju, foreach ili for-each petlja je naredba za prolaženje kroz stavke u kolekciji. Za razliku od drugih for petlji, foreach petlje obično ne održavaju izričiti brojač: oni u suštini kažu "uradi ovo svima u ovom setu", umjesto "uradi ovo n puta". Ovime se izbegava moguća "greška za jedan" i čini kod lakšim za čitanje.

Sintaksa

[uredi | uredi kod]

Sintaksa varira među jezicima. Najviše se koristi jednostavna reč  for, otprilike ovako:

for each item in collection:
  do something to item

Jezička podrška

[uredi | uredi kod]

Neki od jezika sa podrškom za foreach petlje sadrže ABC, ActionScript, Ada, C++11, C#, CFML, Cobra, D, Daplex (jezik upita), ECMAScript, Erlang, Java (još od 1.5, koristi zadržanu reč for za for petlju i  foreach petlju), Javaskript, Objective-C (još od 2.0), ParaSail, Perl, PHP, Pajton, REALbasic, Rubi, Scala, Smalltalk, Svift, Tcl, tcsh, Unix shells, Visual Basic .NET and Windows PowerShell. Značajni jezici bez foreach su C i C++ pre C++11.

ActionScript podržava foreach petlje od strane ključa/indeksa i vrednosti:

for ( var key:String in someObject ) {
   var value = someObject[key];
   trace( "someObject[" + key + "] = " + someObject[key] );
}

for each ( var value in someArray ) {
   trace( typeof value + " " + value );
}
Beleška
someArray može biti bilo koji objekat i someObject može biti niz, ali tipično korišćenje je kako je i prikazano

Ada podržava foreach petlje kao deo normalne for petlje. Recimo da je H neki niz:

for I in X'Range loop
   X (I) := Get_Next_Element;
end loop;
Beleška
Ova sintaksa je najčešće korišćena u nizovima, ali će takođe raditi i sa ostalim tipovima kada je potpuna iteracija potrebna

Ada 2012 je generalizovala petlje u foreach petlje za bilo koju vrstu sadržine (nizove, liste, mape,...):

for Obj of X loop
   -- Work on Obj
end loop;

C jezik nema zbirke ili foreach konstrukcije. Ona, međutim, ima veliki broj standardnih strukturnih podataka koji mogu biti teški kao zbirke, i foreach mogu biti lako napravljene sa makroom.

Međutim, postoje dva očigledna problema:

  • Makro je higijenski neispravan - on deklariše novu vrednost u postojećem obimu koji preostaje nakon petlje.
  • Ne možete se definisati jedinstveni foreach makro koji radi sa različitim tipovima zbirke (npr. niz i povezana lista) ili koji se može proširiti na tipove korisnika.

C niska kao zbirka članova:

#include <stdio.h>

/* foreach macro viewing a string as a collection of char values */
#define foreach(ptrvar, strvar) \
char* ptrvar; \
for (ptrvar = strvar; (*ptrvar) != '\0'; *ptrvar++)

int main(int argc, char** argv) {
 char* s1 = "abcdefg";
 char* s2 = "123456789";
 foreach (p1, s1) {
  printf("loop 1: %c\n", *p1);
 }
 foreach (p2, s2) {
  printf("loop 2: %c\n", *p2);
 }
 return 0;
}

C int niz kao zbirka od int (niz veličine poznat prilikom kompilacije)

#include <stdio.h>

/* foreach macro viewing an array of int values as a collection of int values */
#define foreach(intpvar, intarr) \
int* intpvar; \
for (intpvar = intarr; intpvar < (intarr + (sizeof(intarr)/sizeof(intarr[0]))); ++intpvar)

int main(int argc, char** argv) {
 int a1[] = {1, 1, 2, 3, 5, 8};
 int a2[] = {3, 1, 4, 1, 5, 9};
 foreach (p1, a1) {
  printf("loop 1: %d\n", *p1);
 }
 foreach (p2, a2) {
  printf("loop 2: %d\n", *p2);
 }
 return 0;
}

Najčešće: string ili niz kao zbirka (veličina zbirke poznata u vreme pokretanja)

Beleška: idxtype se može izbrisati i typeof(col[0]) se može koristiti na mestu GCC
#include <stdio.h>
#include <string.h>

/* foreach macro viewing an array of given type as a collection of values of given type */
#define arraylen(arr) (sizeof(arr)/sizeof(arr[0]))
#define foreach(idxtype, idxpvar, col, colsiz) \
idxtype* idxpvar; \
for (idxpvar = col; idxpvar < (col + colsiz); ++idxpvar)

int main(int argc, char** argv) {
 char* c1 = "collection";
 int c2[] = {3, 1, 4, 1, 5, 9};
 double* c3;
 int c3len = 4;
 c3 = (double*)calloc(c3len, sizeof(double)); 
 c3[0] = 1.2; c3[1] = 3.4; c3[2] = 5.6; c3[3] = 7.8;

 foreach (char, p1, c1, strlen(c1)) {
  printf("loop 1: %c\n", *p1);
 }
 foreach (int, p2, c2, arraylen(c2)) {
  printf("loop 2: %d\n", *p2);
 }
 foreach (double, p3, c3, c3len) {
  printf("loop 3: %.1lf\n", *p3);
 }
 return 0;
}

Pod pretpostavkom da je myArray  niz celih brojeva:

foreach (int x in myArray) { Console.WriteLine(x); }

LINQ daje sledeću sintaksu, prihvatanje delegata ili lambda ekspresije:

myArray.ToList().ForEach(x => Console.WriteLine(x));

C++11 daje  forič petlju. Sintaksa je slična Javi:

#uključuje <iostream>

int main()
{
  int myint[] = {1,2,3,4,5};

  for (int i : myint)
  {
    std::cout << i << std::endl;
  }
}

Trenutno, C++11 opseg zasnovan na izjavama je realizovan u GCC (još u verziji 4.6), jeka (još u verziji 3.0) i Vižual C++ 2012 (verzija 11 [1]) Qt, C++ okvir, nudi makro  forič petlje[2] koristi STL iterator interfejs:

#uključuje <QList>
#uključuje <QDebug>

int main()
{
  QList<int> list;

  list << 1 << 2 << 3 << 4 << 5;

  foreach (int i, list)
  {
    qDebug() << i;
  }
}

Boost, set besplatnih portabla sa recenzijom C++ biblioteka takođe pruža foreach petlje:[3]

#uključuje <boost/foreach.hpp>
#uključuje<iostream>
 
int main()
{
  int myint[] = {1,2,3,4,5};
 
  BOOST_FOREACH(int &i, myint)
  {
    std::cout << i << std::endl;
  }
}

C++/CLI

[uredi | uredi kod]

C++/CLI jezika predlaže konstrukciju sličnu C#.

Pretpostavimo da je myArray niz celih brojeva:

   for each (int x in myArray)
   {
       Console::WriteLine(x);
   }

Script syntax

[uredi | uredi kod]
// nizovi
arrayeach([1,2,3,4,5], function(v){
    writeOutput(v);
});

// ili

for (v in [1,2,3,4,5]){
    writeOutput(v);
}

// ili

// (Reilo samo; ne podržava u ColdFusion-u)
letters = ["a","b","c","d","e"];
letters.each(function(v){
    writeOutput(v); // abcde
});

// strukture
for (k in collection){
    writeOutput(collection[k]);
}

// ili

structEach(collection, function(k,v){
    writeOutput("key: #k#, value: #v#;");
});

// ili
// (Reilo samo; ne podržava u ColdFusion-u)
collection.each(function(k,v){
    writeOutput("key: #k#, value: #v#;");
});

Tag syntax

[uredi | uredi kod]
<!--- arrays --->
<cfloop index="v" array="#['a','b','c','d','e']#">
  <cfoutput>#v#</cfoutput><!--- a b c d e  --->
</cfloop>

Imati na umu da CFML pogrešno identifikuje vrednost kao "indeks" u ovoj konstrukciji;  index promenljiva prima stvarnu vrednost elementa niza , a ne njegov indeks.

<!--- structs --->
<cfloop item="k" collection="#collection#">
    <cfoutput>#collection[k]#</cfoutput>
</cfloop>

Common Lisp

[uredi | uredi kod]

Common Lisp omogućava foreach funkcionalnost sa dolist makro:

(dolist (i '(1 3 5 6 8 10 14 17))
  (print i))

ili sa mapcar funkcijom:

(mapcar #'print '(1 3 5 6 8 10 14 17))
foreach(item; set) {
  // uraditi nešto stavki
}
or
foreach(argument) {
  // propustiti vrednost
}
for (final element in someCollection) {
  // uraditi nešto sa elementom
}

Foreach podrška je dodata u Delphi 2005, i koristi popisivača promenljive koja mora biti deklarisana u var sekciji.

for enumerator in collection do
begin
  //uraditi nešto ovde
end;

Iteracioni (forič) oblik Eiffel petlje uvodi ključ across.

U ovom primeri, svaki element strukture my_list je ištampan:

            across my_list as ic loop print (ic.item) end

Lokalni entitet ic je instanca klase biblioteka ITERATION_CURSOR. Funkcija item pruža pristup svakom elementu strukture. Potomci klase ITERATION_CURSOR mogu biti kreirani za rukovanje specijalizovanih  iteracija algoritama. Vrste objekata koji mogu biti ponovo pronađeni (my_list in the example)su bazirani na klasama koje naslede iz klase biblioteke ITERABLE.

Ponavljanje iz Eiffel petlje se takođe može koristiti kao logičku ekspresija kada je ključna reč loop zamenjena ili saall (vrši univerzalnu kvantifikaciju) ili sa some (vrši egzistencijalnu kvantifikaciju).

Ovo ponavljanje je logička ekspresija koja je tačna ako sve stavke u my_list broje više od tri:

            across my_list as ic all ic.item.count > 3 end

Nastavak je tačan ako barem jedna od stavki broji više od tri :

            across my_list as ic some ic.item.count > 3 end

Go foreach petlja može se koristiti za petlju preko niza, kriške, niske, mape, ili preko kanala.

Koristeći formu od dve vrednosti, dobijamo indeks/ključ (prvi element) i vrednost (drugi element):

for index, value := range someCollection {
	// Uraditi nešto za indeksiranje i vrednosovanje
}

Koristeći formu od jedne vrednost, dobijamo indeks/ključ (prvi element):

for index := range someCollection {
	// Uraditi nešto indeksu
}

[4]

Groovy podržava for petlje preko zbirki poput nizova, listi i opsega :

def x = [1,2,3,4]
for (v in x) // petlja nad 4-elementa niza h
{
    println v
}

for (v in [1,2,3,4]) // petlja nad 4-elementa literalne liste
{
    println v
}

for (v in 1..4) // petlja nad opsegom 1..4
{
    println v
}

Groovy takođe podržava  C-stil za petlju sa indeksom niza :

for (i = 0; i < x.size(); i++)
{
    println x[i]
}

Zbirke u Groovy takođe mogu biti ponovljene korišćenjem ključne reči svaki i zatvaranjem. Po podrazumevanom podešavanju, petlja lutka je tako nazvana

x.each{ println it } // štampa svaki lementa niza h
x.each{i-> println i} // ekvivalentno liniji ispod, samo lutka petlje eksplicitno nazvana "i"

Petlja preko listi sa  monadic aktivnostima koristi mapM_i  forM_ (mapM_ sa obrnutim argumentima) iz Control.Monad:

kod štampa
mapM_ print [1..4]
1
2
3
4
forM_ "test" $ \char -> do 
    putChar char
    putChar char
tteesstt

Takođe je moguće generalizovati te funkcije da rade na aplikativnim funktorima pre nego monade i bilo koje strukture podataka koje prolaze koristeći traverse (for sa obrnutim argumentima) i mapM (forM sa obrnutim argumentima) iz Data.Traversable.

for (value in iterable) {
    trace(value);
}

Lambda.iter(iterable, function(value) trace(value));

Foreach-konstrukcija je uvedena u JDK 1.5.0.[5]

Zvanični izvori koriste nekoliko imena za konstrukciju. To se naziva "Poboljšanje za Petlju",[5] "For-Each Petlja",[6] i "foreach izjava".[7]

for (type item: iterableCollection) {
    // Uradi nešto stavki
}

Za ne naređeno ponavljanje nad ključevima u Object, JavaScript karakterišefor...in petlju:

for (var key in object) {
    // Raditi nešto sa objektom [ključem]
}

Da bi se ograničilo ponavljanje na sopstvenim osobinama objekta, isključujući one nasleđene kroz prototip lanca, ponekad je korisnije dodati hasOwnProperty() test, ako je podržano od strane JavaScript-a(za WebKit/Safari, to znači "u verziji 3 ili kasnije").

for (var key in object) {
    if (object.hasOwnProperty(key)) {
        // Raditi nešto sa objektom [ključem]
    }
}

U ECMAScript 5 moguće je koristiti metod ključeva funkcije Object da ponovi preko sopstvenih ključeva prirodnije. [8]

var book = { name: "A Christmas Carol", author: "Charles Dickens" }; 
Object.keys(book).forEach(function (key, index) {
    alert("PropertyName = " key + " Property Value = " + book[key]);
}

U ECMAScript 5 takođe je moguće koristiti forEach izvornog niza.[9]

var animals = ['pas', 'mačka', 'medved'];
animals.forEach(function(animal, index) {
    alert(index + ':' + animal); // '0:pas', '1:mačka', '2:medved'
});

Gecko-ov JavaScript endžin takođe ima for each...in izjavu, koja primenjuje preko vrednosti u objektu, a ne preko ključeva.[10]

Imajte na umu da nije preporučljivo koristiti for...in ili for each...in izjavu na niz objekata u  JavaScript-i, zbog gore pomenutog problema imovine nasleđenog od prototipa, kao i zato što on samo primenjuje već postojeće ključeve i ne garantuje da će ponoviti nad elementima u određenom smeru. Trebalo bi koristiti redovan S-stil petlje. EcmaScript 6 ima for..of   za ponavljanje indeksa nad generatorima, nizovima i više.

for item = array
%uradi nešto
end

For each petlje su podržani u Mintu i poseduju sledeću sintaksu :

for each element of list
    /* 'Uradi nešto.' */
end

Zanimljivo je da for (;;) ili while (true) beskonačna petlja u Mintu može biti napisana koristeći for each petlju i beskonačno dugu listu.[11]

import type
/* 'Ova funkcija je takođe mapirana'
 * 'svaki broj indeksa i '
 * 'beskonačno duga lista.'
 */
sub identity(x)
    return x
end
/* 'Sledeće stvara listu'
 * '[0, 1, 2, 3, 4, 5, ..., beskonačnost]'
 */
infiniteList = list(identity)
for each element of infiniteList
    /* 'Radi nešto večno.' */
end

Foreach petlje, pod nazivom Objective-C, su u početku podržani u Objective-C 2.0. Mogu se koristiti da ponavljaju bilo koji objekat koji iplementira NSFastEnumeration protokol, uključujući i NSArray, NSDictionary (vrši ponavljanje preko ključeva), NSSet, etc.

NSArray *a = [NSArray new]; // Bilo koja klasa sadržine može biti supstituisana
for(id obj in a) { // Imati na umu da dinamično kucanje (ne moramo da znamo
                                  // Tip objektna koji je sačuvan u 'a'. Ustvari, može biti
                                  // mnogo različitih tipova objekta u redu.

    printf("%s\n", [[obj description] UTF8String]);  // Najviše se koristi UTF8String sa %s
    NSLog(@"%@", obj);                               // Izlazi kao objekat
}

NSArrays mogu takođe da emituju poruku njihovim članovima:

NSArray *a = [NSArray new];

[a makeObjectsPerformSelector:@selector(printDescription)];

Gde su blokovi dostupni, NSArray može automatski da izvrši blokadu nad sadržanom stavkom:

[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
	{
		NSLog(@"obj %@", obj);
		if ([obj shouldStopIterationNow])
			*stop = YES;
	}];

Tip kolekcije koji se ponavlja će diktirati stavku koja će se vraćati prilikom svakog ponavljanja. Na primer:

NSDictionary *d = [NSDictionary new];

for(id key in d) {
    NSObject *obj = [d objectForKey:key];      // Koristimo (jedinstven) ključ kako bi se pristupilo (moguće nejednistvenom) objektu.
    NSLog(@"%@", obj);
}

Još od kad je OCaml Funkcionalno programiranje, jednakost foreach petlje se može postići pomoću funkcije biblioteke nad listama i nizovima.

For Liste:

List.iter (fun x -> print_int x) [1;2;3;4];;

ili kraće:

List.iter print_int [1;2;3;4];;

For Nizovi:

Array.iter (fun x -> print_int x) [|1;2;3;4|];;

ili kraće:

Array.iter print_int [|1;2;3;4|];;

ParaSail paralelno programskom jeziku podržava nekoliko vrsti iteratora, uključujući i opšti  "for ič" iterator nad sadrživačem:

var Con : Container<Element_Type> := ...
// ...
for each Elem of Con concurrent loop // petlja takođe može biti "napredna" ili "nazadujuća" ili neodređena (podrzumevana)
  // ... raditi nešto sa Elem
end loop

ParaSail takođe podržava filtere nad iteratorima, kao i mogućnost da se poziva i na ključ i na vrednost mape. Ovde iteracija nad elementima  "My_Map" bira samo one elemente kod kojih su ključevi u "My_Set":

var My_Map : Map<Key_Type => Univ_String, Value_Type => Tree<Integer>> := ...
const My_Set : Set<Univ_String> := ["abc", "def", "ghi"];

for each [Str => Tr] of My_Map {Str in My_Set} forward loop
   // ... raditi nešto sa Str ili Tr
end loop

ISO 10206:1990 standard je predstavio iteraciju preko određene vrste u Pascal-u:

var
  elt: ElementType;
  eltset: set of ElementType;

{...}

for elt in eltset do
  { ... uraditi nešto sa elt }

U Perl programskom jeziku, forič (što je ekvivalentno kraćem for ) može se koristiti za prebacivanje elemenata liste. Izraz koji označava zbiku petlje se ocenjuje u listu konteksta i svaka stavka rezultata liste je, zauzvrat, šifrovan za vrednost petlje.

Bukvalni primer liste:

foreach (1, 2, 3, 4) {
    print $_;
}

Primer niza:

foreach (@arr) {
    print $_;
}
foreach $x (@arr) { #$x je element u @arr
    print $x;
}

Heš primer:

foreach $x (keys %hash) {
    print $x . " = " . $hash{$x}; # $x je ključ u %hash i $hash{$x} je njegova vrednost
}

Direktna modifikacija članova zbirke:

@arr = ( 'remove-foo', 'remove-bar' );
foreach $x (@arr){
    $x =~ s/remove-//;
}
# Sada @arr = ('foo', 'bar');
 
foreach ($set as $value)
{
    // Uraditi nešto nad $value;
}

Takođe je moguće ekstraktovati oba ključa i vrednosti koristeći se alternativnom sintaksom:

foreach ($set as $key => $value) {
    echo "{$key} ima vrednost od {$value}";
}

Direct modification of collection members:

$arr = array(1, 2, 3);
foreach ($arr as &$value) { // Primetiti &, $value je referenca originalne vrednosti unutar $arr
    $value++;
}
// Sada $arr = array(2, 3, 4);

// takođe radi sa potpunom sintaksom
foreach ($arr as $key => &$value) {
    $value++;
}
for item in iterable_collection:
    # uraditi nešto sa stavkom

Pajtonov zadatak torki, u potpunosti dostupan u  foreach petlji, takođe čini trivijalno ponavljanje nad (ključ, vrednost) parovima u asocijativnom nizu:

for key, value in some_dict.items(): # direct iteration on a dict iterates on its keys
    # radi nešto

Što se tiče for ... in je jedina vrsta petlji u Python-u, ekvivalentna "kontra" petlji pronađenoj u drugim jezicima ...

for i in range(len(seq)):
    # radi nešto sa seq[i]

... mada koristi enumerate funkciju, koja se smatra "Pythonic":

for i, item in enumerate(seq):
    # radi nešto sa stavkom
    # moguće je da dodeljuje seq[i]
(for ([item set])
  (do-something-with item))

ili koristeći konvencijalnu šemu for-each funkcije:

(for-each do-something-with a-list)

do-something-withje jedan-argument funkcija.

set.each do |item|
  # uraditi nešto stavki
end

ili

for item in set
  # uraditi nešto stavki
end

Takođe možete koristiti sa crtom.

set.each do |item,value|
  # uraditi nešto stavki
  # uraditi nešto nad vrednosti
end
// vraća listu modifikovanih elemenata
items map { x => doSomething(x) }
items map multiplyByTwo

for {x <- items} yield doSomething(x)
for {x <- items} yield multiplyByTwo(x)

// ne vraća ništa, samo izvršava akciju
items foreach { x => doSomething(x) }
items foreach println

for {x <- items} doSomething(x)
for {x <- items} println(x)
(for-each do-something-with a-list)

do-something-with je jedan-argument funkcija.

collection do: [:item| "do something to item" ]

Swift koristi forin konstrukcija za ponavljanje kroz članove zbirke.[12]

for thing in someCollection {
    // radi nešto sa stvari
}

 forin petlja se često koristi sa zatvorenim i otvorenim intervalima za ponavljanje kroz telo petlje određeni broj puta.

for i in 0..<10 {
    // 0..<10 konstruiše polu-otvoreni interval, tako da je telo petlje
    // ponovljeno za i = 0, i = 1, …, i = 9.
}

for i in 0...10 {
    // 0...10 konstruiše zatvoreni interval, tako da je telo petlje
    // ponovljeno za i = 0, i = 1, …, i = 9, i = 10.
}

SystemVerilog ima podršku za ponavljanje nad nekim vektorom ili nizom bilo kojih dimenzija koristeći reč foreach.

Trivijalni primer ponavljanja nad nizom celih brojeva je:

kod štampa
int  array_1d[] = '{ 3, 2, 1, 0 };

foreach array_1d[index]
  $display("array_1d[%0d]: %0d", index, array_1d[index]);
array_1d[0]: 3
array_1d[1]: 2
array_1d[2]: 1
array_1d[3]: 0

Složeniji primer ponavljanja nad asocijativnim nizom nizova celih brojeva :

kod štampa
int  array_2d[string][] = '{ "tens": '{ 10, 11 },
                             "twenties": '{ 20, 21 } };

foreach array_2d[key,index]
  $display("array_2d[%s,%0d]: %0d", key, index, array_2d[key,index]);
array_2d[tens,0]: 10
array_2d[tens,1]: 11
array_2d[twenties,0]: 20
array_2d[twenties,1]: 21

Tcl koristi foreach za ponavljanje nad listama. Moguće je navesti više od jednog iteratora promenljive, u čijem slučaju su dodeljene uzastopne vrednosti iz liste.

kod štampa
foreach {i j} {1 2 3 4 5 6} {
    puts "$i $j"
}
1 2
3 4
5 6

Takođe je moguće ponavljanje nad više od jedne liste istovremeno . U nastavku  i preuzima niz navedenih vrednosti prve liste, j niz vrednosti druge liste:

kod štampa
foreach i {1 2 3} j {a b c}  {
    puts "$i $j"
}
1 a
2 b
3 c
For Each item In enumerable
    ' Radi nešto sa stavkom.
Next

ili bez vrste zaključivanja:

For Each item As type In enumerable
    ' Radi nešto sa stavkom.
Next
foreach ($item in $set) {
    # Radi nešto sa $item
}

Iz pajplajna

$list | ForEach-Object {Write-Host $_}
 <xsl:for-each select="set">
   <!-- radi nešto za elemente u <set> -->
 </xsl:for-each>

[13]

Povezano

[uredi | uredi kod]

Reference

[uredi | uredi kod]
  1. "C++11 Features in Visual C++ 11 - Visual C++ Team Blog - Site Home - MSDN Blogs".
  2. "Qt 4.2: Generic Containers" Arhivirano 2015-11-23 na Wayback Machine-u.
  3. Eric Niebler (2013-01-31).
  4. "Range Clause".
  5. 5,0 5,1 "Enhanced for Loop - This new language construct[.
  6. "The For-Each Loop" "The For-Each Loop".
  7. "Implementing this interface allows an object to be the target of the "foreach" statement."
  8. "Object.keys".
  9. "Array.prototype.forEach".
  10. "JavaScript - for each...in statement" Arhivirano 2008-11-22 na Wayback Machine-u.
  11. Chu, Oliver.
  12. The Swift Programming Language (Swift 2.2): Control Flow
  13. "XSLT <xsl:for-each> Element" Arhivirano 2015-10-30 na Wayback Machine-u.