Przerwanie nested for loops

Przerwanie nested for loops
OS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 20
0

Czy w c# istnieje mechanizm, który pozwala na przerwanie nested loops?

Kopiuj
for (int a = 0; a <= x1; a++)
for (int b = 0; b <= y1; b++) {
  if (warunek) {
  //zakończ iteracje na wszystkich pętlach
  }
}
AD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 342
2

Break?

Spine
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6959
3

@Adin: Wtedy wyjdziesz tylko z pętli b.
Pętla a wykona się kolejny raz...

Kopiuj
using System;

public class Test
{
	public static void Main()
	{
		int x1 = 3;
		int y1 = 4;
	
		for (int a = 0; a <= x1; a++)
		{
			for (int b = 0; b <= y1; b++)
			{
				if (a == 2 && b == 2)
				{
					Console.WriteLine("zakończ iteracje na wszystkich pętlach");
					break;
				}
				
				Console.WriteLine(string.Format("a:{0}, b:{1}", a, b));
			}
		}
	}
}

wynik:

Kopiuj
a:0, b:0
a:0, b:1
a:0, b:2
a:0, b:3
a:0, b:4
a:1, b:0
a:1, b:1
a:1, b:2
a:1, b:3
a:1, b:4
a:2, b:0
a:2, b:1
zakończ iteracje na wszystkich pętlach
a:3, b:0
a:3, b:1
a:3, b:2
a:3, b:3
a:3, b:4

Wyszło tylko z jednej pętli. OP pytał o loops, czyli liczba mnoga.


  1. Jeśli tylko się da, to najlepiej tak zorganizować kod, żeby dało się wyjść z pętli za pomocą return.
    Czyli od razu wychodzisz z całej funkcji, a nie tylko z pętli.
  2. Inne rozwiązanie to instrukcja goto: https://www.programiz.com/csharp-programming/goto
  3. Jeszcze inne rozwiązanie to użycie zmiennej typu bool. Kiedy będziesz chciał wyjść ze wszystkich pętli, to po prostu w zagnieżdżonej pętli ustawisz zmienną na true i wykonasz break. W pozostałych pętlach sprawdzisz, czy wartość tej zmiennej to true - jeśli tak, to te pętle też niech wykonają break.
SL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1017
3

Jest goto, z drugiej strony dokumentacja odradza (i dobrze)

screenshot-20250202023014.png

LukeJL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8487
8

Wydzielenie funkcji jest zwykle najbardziej czytelnym sposobem, bo wtedy masz jakiś konkretny kawałek kodu, który ma swoją nazwę, który zwraca jakąś konkretną wartość (np. true/false) i który można potem użyć w innych miejscach.

Kopiuj
for (int a = 0; a <= x1; a++)
for (int b = 0; b <= y1; b++) {
  if (warunek) {
  //zakończ iteracje na wszystkich pętlach
  }
}

nie wiem, czy to abstrakcyjny przykład, czy konkretny, ale jeśli konkretny to wygląda jak szukanie czegoś w prostokątnym obszarze pikseli. Zastanów się, czego szukasz i czy nie można by z tego funkcji zrobić.

HI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1862
3

Ewentualnie jakaś flaga ustawiana przez główną pętlą i sprawdzanie jej wewnątrz każdej wewnętrznej.

AN
  • Rejestracja: dni
  • Ostatnio: dni
3

To już prościej spowodować, że warunek pętli zewnętrznej przestanie być spełniony:

Kopiuj
for (int a = 0; a <= x1; a++)
for (int b = 0; b <= y1; b++) {
  if (warunek) {
    a = x1 + 1;
    break;
  }
}
WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
4

Ale po co dodawać jakieś dodatkowe flagi, checki, warunki gdy można zrobić zwykłe goto? :D to naprawde nie gryzie

Ewentualnie wydzielenie do funkcji

OS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 20
0

Dziękuje za pomoc. GOTO mi się najbardziej podoba.

obscurity
  • Rejestracja: dni
  • Ostatnio: dni
8

Jeśli masz zagnieżdżoną pętlę to wydziel ją do osobnej funkcji i zamiast break użyj return. Goto nigdy nie jest poprawną odpowiedzią jeśli chodzi o czytelność kodu.

WeiXiao napisał(a):

to naprawde nie gryzie

naprawdę gryzie. W najmniej odpowiednim momencie

screenshot-20250203204511.png

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
1

@obscurity

Wręcz przeciwnie, goto ma mniejszy narzut kognitywny, bo nie trzeba skakac i analizowac kilku funkcji

Kopiuj
SomePixelTransformation(int [,] arr)
{
	for (int a = 0; a <= x1; a++)
	{
		for (int b = 0; b <= y1; b++)
		{
		  if (xyz)
			goto endLoop;
		}
	}
	
	endLoop:
	
	(...)
	
	return arr;
}

vs

Kopiuj
SomePixelTransformation(int [,] arr)
{
	PerformSomeTransformation(arr);
	
	(...)
	
	return arr;
}

PerformSomeTransformation(int [,] arr)
{
	for (int a = 0; a <= x1; a++)
	{
		for (int b = 0; b <= y1; b++) 
		{
		  if (xyz)
			return arr;
		}
	}
	
	return arr;
}
obscurity
  • Rejestracja: dni
  • Ostatnio: dni
4
WeiXiao napisał(a):

@obscurity

Wręcz przeciwnie, goto ma mniejszy narzut kognitywny, bo nie trzeba skakac i analizowac kilku funkcji

Przecież drugi przykład jest znacznie prostszy do przeanalizowania. Wiem że ciężko na przykładzie tak prostego kodu który się samemu napisało to odczuć ale w pierwszym przypadku widząc kod po raz pierwszy i natrafiając na etykietę musisz przerwać standardową analizę kodu i szukać wszystkich skoków. Jeszcze jak jest jedna etykieta i jeden skok to w porządku ale od tego się zaczyna. Znacznie łatwiej ogarniać mniejsze, nazwane (nazwą metody) fragmenty kodu.

W dobrym kodzie metody są tak proste że w ogóle nie musisz ich analizować bo z nazwy, argumentów i zwracanych wartości od razu wiadomo do czego służą; w przypadku jednej większej metody z goto musisz ją przeanalizować w całości.

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
1

@obscurity

ale w pierwszym przypadku widząc kod po raz pierwszy i natrafiając na etykietę musisz przerwać standardową analizę kodu i szukać wszystkich skoków.

W pierwszym mam te etykietę dosłownie przed oczami i co najwyżej mogę przerwać analizę, a w drugim MUSZĘ ją przerwać i zerknąć niżej, albo scrollnac, albo przeskoczyć.

W dobrym kodzie metody są tak proste że w ogóle nie musisz ich analizować bo z nazwy, argumentów i zwracanych wartości od razu wiadomo do czego służą; w przypadku jednej większej metody z goto musisz ją przeanalizować w całości.

W dobrym kodzie, jak taki kiedyś spotkam to dam znać.

Pracowałem przy web devie w dotnet, przy low lvlu (fw) w C, przy narzędziach w C++, przy open-source kobyłach z milionami linii

i serio uważam że im mniej tych "uncle bobowych" funkcyjek, które są raz uzywane w całym programie i są na siłe wydzielone, tym niższy narzut kognitywny ma taki kod.

Dla mnie idealny kod ma m.in takie cechy: relatywnie krótki, dobrze opisany, z komentarzami opisującymi dlaczego coś się stało, niewymagający skakania po X metodach (lub nie dej boze plikach) podczas analizy.

loza_prowizoryczna
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1628
0
Oskarlesk napisał(a):

Czy w c# istnieje mechanizm, który pozwala na przerwanie nested loops?

Da się choć wymaga to egzotycznego użycia wątków.

  1. Nested loop jest odpalany na własnym wątku
  2. Kiedy zagnieżdzona pętla wpada na warunek kończący wysyłasz informację (+wynik) do wątku rodziciela
  3. Wątek rodziciela dokonuje aborcji na wątku loopa

W ten sposób możesz efektywnie wyskoczyć z każdego zagnieżdżenia bez nadużywania goto

Spine
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6959
4

Ciekawostka: w PHP break potrafi wyskoczyć z zagnieżdżonej pętli.
break przyjmuje argument liczbowy, który mówi o ile stopni zagnieżdżenia wyskoczyć.

https://www.php.net/manual/en/control-structures.break.php

break accepts an optional numeric argument which tells it how many nested enclosing structures are to be broken out of. The default value is 1, only the immediate enclosing structure is broken out of.

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
1
Spine napisał(a):

Ciekawostka: w PHP break potrafi wyskoczyć z zagnieżdżonej pętli.
break przyjmuje argument liczbowy, który mówi o ile stopni zagnieżdżenia wyskoczyć.

https://www.php.net/manual/en/control-structures.break.php

break accepts an optional numeric argument which tells it how many nested enclosing structures are to be broken out of. The default value is 1, only the immediate enclosing structure is broken out of.

Java też ma takie coś:

Kopiuj
        outer:
        for (String a : foo) {
            for (String b : bar) {
                if (b.equals("buzz")) {
                    System.out.println("Skipping outer loop for " + a + " due to " + b);
                    continue outer;
                }
            }
            System.out.println("Processing " + a);
        }

https://ideone.com/JaVy5w

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2536
0

Jest brzydkie rozwiazanie, ale still ładniejsze niż go:to[1]:

Kopiuj
end = false;
for (int a = 0; a <= x1; a++)
for (int b = 0; b <= y1; b++) {
  if (warunek) {
    end = true;
    break;
  //zakończ iteracje na wszystkich pętlach
  }
  if(end)
  {
    break;
  }
}

Poza tym to wydzielenie do innej funkcji i return.

[1] Jeśli się nie myle to break to też go:to pod spodem, ale reviewer Ci klepnie.

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
0

@Czitels

no ta, o wiele lepsze niż goto, szkoda tylko że buga tam masz :D

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2536
0
WeiXiao napisał(a):

@Czitels

no ta, o wiele lepsze niż goto, szkoda tylko że buga tam masz :D

Ta, jeszcze class, deklaracji funkcji itd brakuje. Nie tylko "var", którego umyślnie nie dodałem, bo nie kojarzyłem jak to jest w c# z deklaracja zmiennych.
Jak się tak czepiasz na CR jak tu to radziłbym przestać, bo jesteś realnie frajerem. Napocisz się w komciach a typ międzyczasie robi na OE, lub gra w lola. Stara metoda na frustratów :D. Sami Ci mówią jak masz pisać kod a Ty robisz coś innego. Potem "yea, sure" i akceptowanie zmian.

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
0

@Czitels

jakie classy/vary? o czym ty piszesz? xd to algorytmicznie nie działa

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2536
0
WeiXiao napisał(a):

@Czitels

jakie classy/vary? o czym ty piszesz? xd to algorytmicznie nie działa

A, czyli zszedłeś niżej, "}" w innej linii. Nawet nie brałem pod uwagę, że ktoś może nie zczaić o co chodzi w powyższym kodzie. xD Jako mod potraktowałbym twoje posty jako zwykły spam.

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
0

ale taki jest point :D

Na sile unikacie uzycia goto bo profesor w szkole wam powiedzial ze to zle

Dodajecie jakies zmienne, flagi, warunki, a koniec koncow wychodzą jakies bugi których nawet nie widzicie na pierwszy rzut oka, dopiero jak ktos wam zwroci uwage :D

z goto by to dzialalo nawet jak gubisz klamry i scope :D

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2536
0

Na sile unikacie uzycia goto bo profesor w szkole wam powiedzial ze to zle

Czy ja gdzieś pisałem, że goto jest złe samo w sobie? Pisałem tylko o CR. Walczysz z wymyślonym potworem :D

z goto by to dzialalo nawet jak gubisz klamry i scope 😄

Szkoda, że już zpushowałem na proda. :D

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
0

@Czitels

Pisałem że masz awersję, a z czego ona wynika to nie wiem, podejrzewałem szkołe albo goto considered harmful 😄

Napocisz się w komciach a typ międzyczasie robi na OE, lub gra w lola.

<troll> OE? Proszę cię, to jakieś rozwiązanie dla klasy średniej lub niższej? dla niewolnika? no bardzo super, lecisz na dwie roboty hehe

Jakbyś po prostu się lepiej urodził, np. w Izraelu, albo miał wujka w PZPN, czy znajomości w establishmencie amerykańskim to byś nie musiał nawet pracować, a gdzie tam jakies OE 😄
</troll>

obscurity
  • Rejestracja: dni
  • Ostatnio: dni
1
WeiXiao napisał(a):

@Czitels

Pisałem że masz awersję, a z czego ona wynika to nie wiem, podejrzewałem szkołe albo goto considered harmful 😄

Ja mam awersję bo pracowałem w językach, w kodzie i w czasach gdzie goto było czymś powszechnym. Profesorzy nie mówią że "goto jest złe" z czapy tylko z doświadczenia a młodsze pokolenie jak zawsze lubi się buntować i kwestionować stare zasady. No i to czasem dobrze ale jakość przeciętnego kodu leci na łeb ostatnimi laty.
Cytując klasyka, ehh coraz więcej amatorów pcha się do zabawy

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5226
0

@obscurity

Profesorzy
doświadczenie

Dobre, nie znałem.

Ja mam awersję bo pracowałem w językach, w kodzie i w czasach gdzie goto było czymś powszechnym.

Ja też pracowałem w języku gdzie goto jest powszechne: C

I jakoś nie miałem z nim żadnego problemu. O wiele, wiele bardziej przerażały mnie mem issues.

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
3
WeiXiao napisał(a):

Na sile unikacie uzycia goto bo profesor w szkole wam powiedzial ze to zle

Nigdy żaden profesor tak nie powiedział.
Ale widzę, że masz jakiś problem z tym słynnym profesorem. Pokaż na misiu gdzie Cię dotykał:
screenshot-20250205174436.png

z goto by to dzialalo nawet jak gubisz klamry i scope :D

Problem z goto nie polega na jego użyciu, tylko na tym, że przy sensownie napisanym kodzie w ogóle nie ma gdzie tej patoinstrukcji wstawić.

Hodor
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
  • Postów: 337
0

Dyskutowanie nad goto to ściśle juniorska dyskusja, aż mi się studia przypomniały

loza_prowizoryczna
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1628
0
somekind napisał(a):

Problem z goto nie polega na jego użyciu, tylko na tym, że przy sensownie napisanym kodzie w ogóle nie ma gdzie tej patoinstrukcji wstawić.

Z tego pośrednio wynika że architekci C# i innych języków z goto zakładali że sensowny kod w nim napisany będzie mniejszością.

Widać doświadczenie.

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
2
loza_prowizoryczna napisał(a):

Z tego pośrednio wynika że architekci C# i innych języków z goto zakładali że sensowny kod w nim napisany będzie mniejszością.

Widać doświadczenie.

Po prostu przewidzieli istnienie @WeiXiao.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.