Форич петља (енгл.For each или foreach) је програмски језик, идиом , за  пролажење кроз ставке у збирци. Foreach се обично користи уместо стандардне for изјаве. За разлику од других for петљи, foreach петље[1][2] обично одржавају неизричити бројач: они у суштини кажу "уради ово свима у овом сету", више него "уради ово х пута". Овиме се избегава могућа  "грешка за један" и чини код лакшим за читање . У објектно оријентисаним језицима итератор, чак и ако имплицитно, се често користи као средство за пролазак.

For each петље се најчешће користе да понове ставке у низу елемената .

Синтакса

уреди

Синтакса варира међу језицима. Највише се користи једноставна реч  for, отприлике овако:

for each item in collection:
  do something to item

Језичка подршка

уреди

Неки од језика са подршком за foreach петље садрже ABC, ActionScript, Ада, C++11, C#, CFML, Cobra, D, Daplex (језик упита), ECMAScript, Erlang, Јава (још од 1.5, користи задржану реч for за for петљу и  foreach петљу), Јаваскрипт, Objective-C (још од 2.0), ParaSail, Перл, PHP, Пајтон, REALbasic, Руби, Scala, Smalltalk, Свифт, Tcl, tcsh, Unix shells, Visual Basic .NET and Windows PowerShell. Значајни језици без foreach су C и C++ пре C++11.

ActionScript подржава foreach петље од стране кључа/индекса и вредности:

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 );
}
Белешка
someArray може бити било који објекат и someObject може бити низ, али типично коришћење је како је и приказано

Ада подржава foreach петље као део нормалне for петље. Рецимо да је Х неки низ:

for I in X'Range loop
   X (I) := Get_Next_Element;
end loop;
Белешка
Ова синтакса је најчешће коришћена у низовима, али ће такође радити и са осталим типовима када је потпуна итерација потребна

Ada 2012 је генерализовала петље у foreach петље за било коју врсту садржине (низове, листе, мапе,...):

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

C језик нема збирке или foreach конструкције. Она, међутим, има велики број стандардних структурних података који могу бити тешки као збирке, и foreach могу бити лако направљене са макроом.

Међутим, постоје два очигледна проблема:

  • Макро је хигијенски неисправан - он декларише нову вредност у постојећем обиму који преостаје након петље.
  • Не можете се дефинисати јединствени foreach макро који ради са различитим типовима збирке (нпр. низ и повезана листа) или који се може проширити на типове корисника.

C ниска као збирка чланова:

#include <stdio.h>
#include <stdlib.h>
/* форич макро за коришћење ниске као колекције карактера */
#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);
 }
 exit(0);
 return(0);
}

C int низ као збирка од int (низ величине познат приликом компилације)

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
/* форич макро види низ целобројних вредности као збирку целобројних вредности */
#define foreach( intpvar, intary ) int* intpvar; for( intpvar=intary; intpvar < (intary + (sizeof(intary)/sizeof(intary[0]))) ; intpvar++)
 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);
 }
 exit(0);
 return(0);
}

Најчешће: стринг или низ као збирка (величина збирке позната у време покретања)

Белешка: idxtype се може избрисати и typeof(col[0]) се може користити на месту GCC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]){
#define foreach(idxtype, idxpvar, col, colsiz ) idxtype* idxpvar; for( idxpvar=col ; idxpvar < (col + (colsiz)) ; idxpvar++)
#define arraylen( ary ) ( sizeof(ary)/sizeof(ary[0]) )
 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 : %3.1lf\n",*p3);
 }
 exit(0);
 return(0);
}

Под претпоставком да је myArray  низ целих бројева:

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

LINQ даје следећу синтаксу, прихватање делегата или ламбда експресије:

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

C++11 даје  форич петљу. Синтакса је слична Јави:

#укључује <iostream>

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

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

Тренутно, C++11 опсег заснован на изјавама је реализован у GCC (још у верзији 4.6), јека (још у верзији 3.0) и Вижуал C++ 2012 (верзија 11[3]) Qt, C++ оквир, нуди макро  форич петље[4] користи STL итератор интерфејс:

#укључује <QList>
#укључује <QDebug>

int main()
{
  QList<int> list;

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

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

Boost, сет бесплатних портабла са рецензијом C++ библиотека такође пружа foreach петље:[5]

#укључује <boost/foreach.hpp>
#укључује<iostream>
 
int main()
{
  int myint[] = {1,2,3,4,5};
 
  BOOST_FOREACH(int &i, myint)
  {
    std::cout << i << std::endl;
  }
}

C++/CLI језика предлаже конструкцију сличну C#.

Претпоставимо да је myArray низ целих бројева:

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

Script syntax

уреди
// низови
arrayeach([1,2,3,4,5], function(v){
    writeOutput(v);
});

// или

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

// или

// (Реило само; не подржава у ColdFusion-у)
letters = ["a","b","c","d","e"];
letters.each(function(v){
    writeOutput(v); // abcde
});

// структуре
for (k in collection){
    writeOutput(collection[k]);
}

// или

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

// или
// (Реило само; не подржава у ColdFusion-у)
collection.each(function(k,v){
    writeOutput("key: #k#, value: #v#;");
});

Tag syntax

уреди
<!--- arrays --->
<cfloop index="v" array="#['a','b','c','d','e']#">
  <cfoutput>#v#</cfoutput><!--- a b c d e  --->
</cfloop>

Имати на уму да CFML погрешно идентификује вредност као "индекс" у овој конструкцији;  index променљива прима стварну вредност елемента низа , а не његов индекс.

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

Common Lisp

уреди

Common Lisp омогућава foreach функционалност са dolist макро:

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

или са mapcar функцијом:

(mapcar #'print '(1 3 5 6 8 10 14 17))
foreach(item; set) {
  // урадити нешто ставки
}
or
foreach(argument) {
  // пропустити вредност
}
for (final element in someCollection) {
  // урадити нешто са елементом
}

Foreach подршка је додата у Delphi 2005, и користи пописивача променљиве која мора бити декларисана у var секцији.

for enumerator in collection do
begin
  //урадити нешто овде
end;

Итерациони (форич) облик Eiffel петље уводи кључ across.

У овом примери, сваки елемент структуре my_list је иштампан:

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

Локални ентитет ic је инстанца класе библиотека ITERATION_CURSOR. Функција item пружа приступ сваком елементу структуре. Потомци класе ITERATION_CURSOR могу бити креирани за руковање специјализованих  итерација алгоритама. Врсте објеката који могу бити поново пронађени (my_list in the example)су базирани на класама које наследе из класе библиотеке ITERABLE.

Понављање из Eiffel петље се такође може користити као логичку експресија када је кључна реч loop замењена или саall (врши универзалну квантификацију) или са some (врши егзистенцијалну квантификацију).

Ово понављање је логичка експресија која је тачна ако све ставке у my_list броје више од три:

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

Наставак је тачан ако барем једна од ставки броји више од три :

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

Go foreach петља може се користити за петљу преко низа, кришке, ниске, мапе, или преко канала.

Користећи форму од две вредности, добијамо индекс/кључ (први елемент) и вредност (други елемент):

for index, value := range someCollection {
	// Урадити нешто за индексирање и вредносовање
}

Користећи форму од једне вредност, добијамо индекс/кључ (први елемент):

for index := range someCollection {
	// Урадити нешто индексу
}

[6]

Groovy подржава for петље преко збирки попут низова, листи и опсега :

def x = [1,2,3,4]
for (v in x) // петља над 4-елемента низа х
{
    println v
}

for (v in [1,2,3,4]) // петља над 4-елемента литералне листе
{
    println v
}

for (v in 1..4) // петља над опсегом 1..4
{
    println v
}

Groovy такође подржава  C-стил за петљу са индексом низа :

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

Збирке у Groovy такође могу бити поновљене коришћењем кључне речи сваки и затварањем. По подразумеваном подешавању, петља лутка је тако названа

x.each{ println it } // штампа сваки лемента низа х
x.each{i-> println i} // еквивалентно линији испод, само лутка петље експлицитно названа "i"

Петља преко листи са  monadic активностима користи mapM_и  forM_ (mapM_ са обрнутим аргументима) из Control.Monad:

код штампа
mapM_ print [1..4]
1
2
3
4
forM_ "test" $ \char -> do 
    putChar char
    putChar char
tteesstt

Такође је могуће генерализовати те функције да раде на апликативним функторима пре него монаде и било које структуре података које пролазе користећи traverse (for са обрнутим аргументима) и mapM (forM са обрнутим аргументима) из Data.Traversable.

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

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

Foreach-конструкција је уведена у JDK 1.5.0.[7]

Званични извори користе неколико имена за конструкцију. То се назива "Побољшање за Петљу",[7] "For-Each Петља",[8] и "foreach изјава".[9]

for (type item: iterableCollection) {
    // Уради нешто ставки
}

За не наређено понављање над кључевима у Object, JavaScript карактеришеfor...in петљу:

for (var key in object) {
    // Радити нешто са објектом [кључем]
}

Да би се ограничило понављање на сопственим особинама објекта, искључујући оне наслеђене кроз прототип ланца, понекад је корисније додати hasOwnProperty() тест, ако је подржано од стране JavaScript-а(за WebKit/Safari, то значи "у верзији 3 или касније").

for (var key in object) {
    if (object.hasOwnProperty(key)) {
        // Радити нешто са објектом [кључем]
    }
}

У ECMAScript 5 могуће је користити метод кључева функције Object да понови преко сопствених кључева природније. [10]

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

У ECMAScript 5 такође је могуће користити forEach изворног низа.[11]

var animals = ['пас', 'мачка', 'медвед'];
animals.forEach(function(animal, index) {
    alert(index + ':' + animal); // '0:пас', '1:мачка', '2:медвед'
});

Gecko-ов JavaScript енџин такође има for each...in изјаву, која примењује преко вредности у објекту, а не преко кључева.[12]

Имајте на уму да није препоручљиво користити for...in или for each...in изјаву на низ објеката у  JavaScript-и, због горе поменутог проблема имовине наслеђеног од прототипа, као и зато што он само примењује већ постојеће кључеве и не гарантује да ће поновити над елементима у одређеном смеру. Требало би користити редован С-стил петље. EcmaScript 6 има for..of   за понављање индекса над генераторима, низовима и више.

for item = array
%уради нешто
end

For each петље су подржани у Минту и поседују следећу синтаксу :

for each element of list
    /* 'Уради нешто.' */
end

Занимљиво је да for (;;) или while (true) бесконачна петља у Минту може бити написана користећи for each петљу и бесконачно дугу листу.[13]

import type
/* 'Ова функција је такође мапирана'
 * 'сваки број индекса i '
 * 'бесконачно дуга листа.'
 */
sub identity(x)
    return x
end
/* 'Следеће ствара листу'
 * '[0, 1, 2, 3, 4, 5, ..., бесконачност]'
 */
infiniteList = list(identity)
for each element of infiniteList
    /* 'Ради нешто вечно.' */
end

Foreach петље, под називом Objective-C, су у почетку подржани у Objective-C 2.0. Могу се користити да понављају било који објекат који иплементира NSFastEnumeration протокол, укључујући и NSArray, NSDictionary (врши понављање преко кључева), NSSet, etc.

NSArray *a = [NSArray new]; // Било која класа садржине може бити супституисана
for(id obj in a) { // Имати на уму да динамично куцање (не морамо да знамо
                                  // Тип објектна који је сачуван у 'a'. У ствари, може бити
                                  // много различитих типова објекта у реду.

    printf("%s\n", [[obj description] UTF8String]);  // Највише се користи UTF8String са %s
    NSLog(@"%@", obj);                               // Излази као објекат
}

NSArrays могу такође да емитују поруку њиховим члановима:

NSArray *a = [NSArray new];

[a makeObjectsPerformSelector:@selector(printDescription)];

Где су блокови доступни, NSArray може аутоматски да изврши блокаду над садржаном ставком:

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

Тип колекције који се понавља ће диктирати ставку која ће се враћати приликом сваког понављања. На пример:

NSDictionary *d = [NSDictionary new];

for(id key in d) {
    NSObject *obj = [d objectForKey:key];      // Користимо (јединствен) кључ како би се приступило (могуће неједниственом) објекту.
    NSLog(@"%@", obj);
}

Још од кад је OCaml Функционално програмирање, једнакост foreach петље се може постићи помоћу функције библиотеке над листама и низовима.

For Листе:

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

или краће:

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

For Низови:

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

или краће:

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

ParaSail паралелно програмском језику подржава неколико врсти итератора, укључујући и општи  "фор ич" итератор над садрживачем:

var Con : Container<Element_Type> := ...
// ...
for each Elem of Con concurrent loop // петља такође може бити "напредна" или "назадујућа" или неодређена (подрзумевана)
  // ... радити нешто са Elem
end loop

ParaSail такође подржава филтере над итераторима, као и могућност да се позива и на кључ и на вредност мапе. Овде итерација над елементима  "My_Map" бира само оне елементе код којих су кључеви у "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
   // ... радити нешто са Str или Tr
end loop

ISO 10206:1990 стандард је представио итерацију преко одређене врсте у Pascal-у:

var
  elt: ElementType;
  eltset: set of ElementType;

{...}

for elt in eltset do
  { ... урадити нешто са elt }

У Perl програмском језику, форич (што је еквивалентно краћем for ) може се користити за пребацивање елемената листе. Израз који означава збику петље се оцењује у листу контекста и свака ставка резултата листе је, заузврат, шифрован за вредност петље.

Буквални пример листе:

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

Пример низа:

foreach (@arr) {
    print $_;
}
foreach $x (@arr) { #$x је елемент у @arr
    print $x;
}

Хеш пример:

foreach $x (keys %hash) {
    print $x . " = " . $hash{$x}; # $x је кључ у %hash и $hash{$x} је његова вредност
}

Директна модификација чланова збирке:

@arr = ( 'remove-foo', 'remove-bar' );
foreach $x (@arr){
    $x =~ s/remove-//;
}
# Сада @arr = ('foo', 'bar');
 
foreach ($set as $value)
{
    // Урадити нешто над $value;
}

Такође је могуће екстрактовати оба кључа и вредности користећи се алтернативном синтаксом:

foreach ($set as $key => $value) {
    echo "{$key} има вредност од {$value}";
}

Direct modification of collection members:

$arr = array(1, 2, 3);
foreach ($arr as &$value) { // Приметити &, $value је референца оригиналне вредности унутар $arr
    $value++;
}
// Сада $arr = array(2, 3, 4);

// такође ради са потпуном синтаксом
foreach ($arr as $key => &$value) {
    $value++;
}
for item in iterable_collection:
    # урадити нешто са ставком

Пајтонов задатак торки, у потпуности доступан у  foreach петљи, такође чини тривијално понављање над (кључ, вредност) паровима у асоцијативном низу:

for key, value in some_dict.items(): # direct iteration on a dict iterates on its keys
    # ради нешто

Што се тиче for ... in је једина врста петљи у Python-у, еквивалентна "контра" петљи пронађеној у другим језицима ...

for i in range(len(seq)):
    # ради нешто са seq[i]

... мада користи enumerate функцију, која се сматра "Pythonic":

for i, item in enumerate(seq):
    # ради нешто са ставком
    # могуће је да додељује seq[i]
(for ([item set])
  (do-something-with item))

или користећи конвенцијалну шему for-each функције:

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

do-something-withje један-аргумент функција.

set.each do |item|
  # урадити нешто ставки
end

или

for item in set
  # урадити нешто ставки
end

Такође можете користити са цртом.

set.each do |item,value|
  # урадити нешто ставки
  # урадити нешто над вредности
end
// враћа листу модификованих елемената
items map { x => doSomething(x) }
items map multiplyByTwo

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

// не враћа ништа, само извршава акцију
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 је један-аргумент функција.

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

Swift користи forin конструкција за понављање кроз чланове збирке.[14]

for thing in someCollection {
    // ради нешто са ствари
}

 forin петља се често користи са затвореним и отвореним интервалима за понављање кроз тело петље одређени број пута.

for i in 0..<10 {
    // 0..<10 конструише полу-отворени интервал, тако да је тело петље
    // поновљено за i = 0, i = 1, …, i = 9.
}

for i in 0...10 {
    // 0...10 конструише затворени интервал, тако да је тело петље
    // поновљено за i = 0, i = 1, …, i = 9, i = 10.
}

SystemVerilog има подршку за понављање над неким вектором или низом било којих димензија користећи реч foreach.

Тривијални пример понављања над низом целих бројева је:

код штампа
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

Сложенији пример понављања над асоцијативним низом низова целих бројева :

код штампа
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 користи foreach за понављање над листама. Могуће је навести више од једног итератора променљиве, у чијем случају су додељене узастопне вредности из листе.

код штампа
foreach {i j} {1 2 3 4 5 6} {
    puts "$i $j"
}
1 2
3 4
5 6

Такође је могуће понављање над више од једне листе истовремено . У наставку  i преузима низ наведених вредности прве листе, j низ вредности друге листе:

код штампа
foreach i {1 2 3} j {a b c}  {
    puts "$i $j"
}
1 a
2 b
3 c
For Each item In enumerable
    ' Ради нешто са ставком.
Next

или без врсте закључивања:

For Each item As type In enumerable
    ' Ради нешто са ставком.
Next
foreach ($item in $set) {
    # Ради нешто са $item
}

Из пајплајна

$list | ForEach-Object {Write-Host $_}
 <xsl:for-each select="set">
   <!-- ради нешто за елементе у <set> -->
 </xsl:for-each>

[15]

Види још

уреди

Референце

уреди
  1. ^ „C++ For_Each Loop”. Архивирано из оригинала 23. 11. 2015. г. Приступљено 29. 10. 2015. 
  2. ^ "D Programming Language foreach Statement Documentation".
  3. ^ "C++11 Features in Visual C++ 11 - Visual C++ Team Blog - Site Home - MSDN Blogs".
  4. ^ "Qt 4.2: Generic Containers" Архивирано на сајту Wayback Machine (23. новембар 2015).
  5. ^ Eric Niebler (2013-01-31).
  6. ^ "Range Clause".
  7. ^ а б "Enhanced for Loop - This new language construct[.
  8. ^ "The For-Each Loop" "The For-Each Loop".
  9. ^ "Implementing this interface allows an object to be the target of the "foreach" statement."
  10. ^ "Object.keys" Архивирано на сајту Wayback Machine (23. новембар 2015).
  11. ^ "Array.prototype.forEach" Архивирано на сајту Wayback Machine (23. новембар 2015).
  12. ^ "JavaScript - for each...in statement" Архивирано на сајту Wayback Machine (22. новембар 2008).
  13. ^ Chu, Oliver.
  14. ^ The Swift Programming Language (Swift 2.2): Control Flow
  15. ^ "XSLT <xsl:for-each> Element" Архивирано на сајту Wayback Machine (30. октобар 2015).