Administratorzy gnysek Opublikowano 29 Grudnia 2011 Administratorzy Udostępnij Opublikowano 29 Grudnia 2011 Dzisiaj na http://www.gmlscripts.com/forums/viewtopic.php?id=1911 natknąłem się na przykład pętli foreach dla GM oraz ds_list. Zaciekawiło mnie na czym polega myk i okazało się, że jest to bardzo prosta sprawa - GM działa także gdy pomijamy średniki, wiec można ten fakt wykorzystać. Zgodnie z dokumentacją Game Makera: for (<wyrazenie1>; <warunek>; <wyrazenie2>) <wyrazenie3> Kroki: Pierwsze wyrażenie jest wykonywane. Sprawdzany jest warunek - jeśli jest prawidłowy, wykonywane jest wyrazenie3, potem wyrazenie 2 i wracamy do kolejności warunek-wyrazenie3-wyrazenie2 tak długo, jak warunek zwraca prawdę Jak widzicie, nigdzie nie jest napisane, że wyrazenie1 musi ustawiać jakąś zmienną, a wyrazenie2 zwiększać/zmniejszać jej wartość. Co więcej - warunek nie musi być znakiem mniejszości czy większości. Napisane jest tylko, że wykonywanie trwa tak długo, jak warunek jest prawdziwy. W takim razie, wystarczy tu wstawić coś, co będzie nam zwracać prawdę lub fałsz - zmienną, lub funkcję. W ten oto sposób powstała pętla foreach. Pomysł jak już wspomniałem nie jest mój, natomiast wersja do obsługi tablic zamiast list jest już jak najbardziej moja (ponieważ w pracy nie mam pełnej wersji Game Makera, nie miałem dostepu do ds_list). SKRYPTY Pierwszy skrypt ustawia tablicę o rozmiarze 10, a potem w pętli foreach wyświetla jej elementy. GML (test) for (i=0; i<10; i+=1) { tablica = i+1; } for( each('tablica',10) as key_value()) { show_message(string(key) + '[' + string(value) +']'); } GML (each) if !variable_global_exists('as') { globalvar as,eachVar,eachSize,key,value; //globalne as = true; } eachVar = argument0; // referencja na tablice eachSize = argument1; key = -1; key_value(); GML (keyvalue) if key < eachSize - 1 { key += 1; value = variable_local_array_get(eachVar, key); } else { as = false; key = -1; value = -1; eachVar = -1; eachSize = -1; } Ha! Jak to działa? jak widzicie, mamy pętlę: for( each('tablica',10) as key_value()) { show_message(string(key) + '[' + string(value) +']'); } Tak naprawdę jest to normalna pętla for, tylko brakuje średników (bo GM ich nie wymaga). GML for( each('tablica',10); as; key_value()) funkcja each definiuje (jeśli nie istnieje) globalną zmienną "as" (jako globalvar, dlatego nie trzeba pisać global. z przodu), oraz kilka innych globalnych zmiennych które są nam tu potrzebne - key i value będą miały aktualny klucz i wartość tablicy. Zgodnie z dokumentacją, pierwsze wyrażenie jest przetwarzane raz. Wyrażenie drugie jest sprawdzane. Nasza globalna as ma wartość true, zatem wyrażenie jest prawdziwe i wykonywane jest wyrazenie3 - czyli ciało pętli. Potem wracamy do wyrazenia2 - które zwiększa nam iterację, a przy okazji sprawdza, czy dochodzimy do konca tablicy - jeśli tak, to ustawi nam as na false. Następnie znów sprawdzany jest warunek - jeśli as == false, no to pętla przestaje działać. Takie proste, a dopiero teraz to odkryłem! Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Saus Opublikowano 29 Grudnia 2011 Udostępnij Opublikowano 29 Grudnia 2011 Genialne, brakowało tego w GML :D Może dużo rzeczy ułatwić. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
I am Lord Opublikowano 29 Grudnia 2011 Udostępnij Opublikowano 29 Grudnia 2011 A do czego taka pętla może być przydatna? Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 29 Grudnia 2011 Autor Administratorzy Udostępnij Opublikowano 29 Grudnia 2011 Z racji, że w GM nie ma tablic asocjacyjnych, to na normalnych tablicach tylko nieznacznie skraca zapis, ale w przypadku ds_list i ds_map - zaoszczędza sporo kodu - ofc tą funkcjonalność trzeba sobie dopisać, ale to zrobię dziś w domu i wrzucę na stronę jako przykład :) http://4programmers.net/C_sharp/Foreach http://php.net/manual/en/control-structures.foreach.php Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
I am Lord Opublikowano 29 Grudnia 2011 Udostępnij Opublikowano 29 Grudnia 2011 Jakoś niewydajne mi się by było to użyteczne przy większych produkcjach. Wydajność ostro leży. GML for( i = 0; i < 20000; i += 1 ) { tekst = string(i); } // test ------------------------------------------------- a=''; time = current_time; for( each('tekst',20000) as key_value()) { a += value; } show_message( "foreach: " + a + "##" + string( current_time - time ) + " ms" ); a=''; time = current_time; for( i = 0; i < 20000; i += 1 ) { a += tekst; } show_message( "for: " + a + "##" + string( current_time - time ) + " ms" ); U mnie forech 875 ms, for 172 ms Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Muuuuczek567 Opublikowano 29 Grudnia 2011 Udostępnij Opublikowano 29 Grudnia 2011 Tak jest z każdym skryptem. Zrób sobie skrypt SIN(x): GML return sin(argument0) i zrób ten sam test, co powyżej, ale z funkcjami sin(x) i SIN(x). hack dla gm : DDD Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 29 Grudnia 2011 Autor Administratorzy Udostępnij Opublikowano 29 Grudnia 2011 Nigdzie nie napisałem, że dla tablic jest to szybsze. variable_local_array_get zjada większość tego czasu :) W przypadku stuktur danych (ds_) będzie to już praktycznie żadna różnica, ale za to jaka wygoda :) Będę miał dostęp do pełnego GM, dopiszę brakującą resztę i pogadamy :) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 30 Grudnia 2011 Autor Administratorzy Udostępnij Opublikowano 30 Grudnia 2011 Proszę, teraz działa z tablicami, ds_list i ds_map :) https://gmclan.org/up23_3_foreach.html Zaznaczam jednak, że to wciąż bardziej ciekawostka bo te same zadania tradycyjną metodą są dużo szybsze. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się