Форич петља
Форич петља (енгл.For each или foreach) је програмски језик, идиом , за пролажење кроз ставке у збирци. Foreach се обично користи уместо стандардне for изјаве. За разлику од других for петљи, foreach петље[1][2] обично одржавају неизричити бројач: они у суштини кажу "уради ово свима у овом сету", више него "уради ово х пута". Овиме се избегава могућа "грешка за један" и чини код лакшим за читање . У објектно оријентисаним језицима итератор, чак и ако имплицитно, се често користи као средство за пролазак.
Синтакса
уредиСинтакса варира међу језицима. Највише се користи једноставна реч 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++/CLI језика предлаже конструкцију сличну C#.
Претпоставимо да је myArray низ целих бројева:
for each (int x in myArray) { Console::WriteLine(x); }
CFML
уреди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 {
// Урадити нешто индексу
}
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
Mint
уреди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-with
je један-аргумент функција.
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 користи for
…in
конструкција за понављање кроз чланове збирке.[14]
for thing in someCollection {
// ради нешто са ствари
}
for
…in
петља се често користи са затвореним и отвореним интервалима за понављање кроз тело петље одређени број пута.
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>
Види још
уредиРеференце
уреди- ^ „C++ For_Each Loop”. Архивирано из оригинала 23. 11. 2015. г. Приступљено 29. 10. 2015.
- ^ "D Programming Language foreach Statement Documentation".
- ^ "C++11 Features in Visual C++ 11 - Visual C++ Team Blog - Site Home - MSDN Blogs".
- ^ "Qt 4.2: Generic Containers" Архивирано на сајту Wayback Machine (23. новембар 2015).
- ^ Eric Niebler (2013-01-31).
- ^ "Range Clause".
- ^ а б "Enhanced for Loop - This new language construct[.
- ^ "The For-Each Loop" "The For-Each Loop".
- ^ "Implementing this interface allows an object to be the target of the "foreach" statement."
- ^ "Object.keys" Архивирано на сајту Wayback Machine (23. новембар 2015).
- ^ "Array.prototype.forEach" Архивирано на сајту Wayback Machine (23. новембар 2015).
- ^ "JavaScript - for each...in statement" Архивирано на сајту Wayback Machine (22. новембар 2008).
- ^ Chu, Oliver.
- ^ The Swift Programming Language (Swift 2.2): Control Flow
- ^ "XSLT <xsl:for-each> Element" Архивирано на сајту Wayback Machine (30. октобар 2015).