Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   множественный перебор (http://www.flasher.ru/forum/showthread.php?t=202674)

in4core 31.07.2013 22:50

множественный перебор
 
Всем привет.
Вот интересно, как обычно справляются с большим кол-ом циклов на однотипных условиях. Приведу пример о чем я.
Имеется вектор CustomSprite . Стоит задача - проверить, изменил ли координату хоть один из набора - и сделать что - то

Код AS3:

for( i = 0; i < v.length; i++)  if( v[i].x > 30 ) doSomthing()

Ок, теперь предположим, что задач несколько аля

Код AS3:

for( i = 0; i < v.length; i++)  if( v[i].x > 30 ) doSomthing1()
for( i = 0; i < v.length; i++)  if( v[i].y > 40 ) doSomthing2()
for( i = 0; i < v.length; i++)  if( v[i].visible ) doSomthing3()

То есть весь смысл в том, что в один цикл не пихнуть, а прописывать N кол-во циклов, не камильфо. Кто как справляется с этим?
Какним нибудь
Код AS3:

repeater( condition:Boolean , action:Function , ...rest)  ???

P.s. в данном случае пример неочень ибо его как раз можно в один пихнуть, но думаю смысл всем понятен

KumoKairo 01.08.2013 00:10

Как вариант можно подписать каждый объект на событие Event.CHANGE (Или на какое-нибудь свое MyLittleSprite.CHANGED_COORDINATES) и сделать обработчик события в одном месте, например в объекте-родителе ваших спрайтов. При изменении координат любого объекта производить диспетчиризацию события Event.CHANGE, на которое вы собственно и подписали объект, и обрабатывать это событие во внешнем обработчике. Тогда не будет никаких циклов.

На несколько задач вопрос решается аналогично - в зависимости от изменения диспетчиризуем одно, второе или третье событие. Или одно и то же событие, но с разными параметрами

Вариант с одним событием:
Код AS3:

...
//Там, где у вас добавляются CustomSprite в вектор:
public function generateSprites():void
{
        for(var i:uint = 0; i < 30; i++)
        {
                var myLittleCustomSprite:CustomSprite = new CustomSprite();
                myLittleCustomSprite.addEventListener(Event.CHANGE, somethingHappened);
                customSpriteVector.push(myLittleCustomSprite);
        }
}
 
public function somethingHappened(e:Event):void
{
        trace("Изменились координаты или того хуже");
}
...
/**
*  В вашем классе CustomSprite
*/

public function changedSomething():void
{
        dispatchEvent(new Event(Event.CHANGE));
}

Вариант с N событиями (один из):
Код AS3:

public class MyCustomEvent extends Event
{
        public MyCustomEvent(type:String, changeTracker:String , bubbles:Boolean = false, cancelable:Boolean = false)
}
...
//Там, где у вас добавляются CustomSprite в вектор:
public function generateSprites():void
{
        for(var i:uint = 0; i < 30; i++)
        {
                var myLittleCustomSprite:CustomSprite = new CustomSprite();
                myLittleCustomSprite.addEventListener(Event.CHANGE, somethingHappened);
                customSpriteVector.push(myLittleCustomSprite);
        }
}
 
public function somethingHappened(e:Event):void
{
        var receivedEvent = e as MyCustomEvent;
        switch(receivedEvent.changeTracker)
        {
                case "changedX":
                        trace("Изменился Х");
                        break;
                case "changedY":
                        trace("Изменился Y");
                        break;
                case "changedVisibility":
                        trace("Изменился visibility");
                        break;
        }
}
...
/**
*  В вашем классе CustomSprite
*/

public function changedSomething(changed:String):void
{
        dispatchEvent(new MyCustomEvent(Event.CHANGE, changed));
}

По моему как то так.

in4core 01.08.2013 16:27

KumoKairo - вообще меня не понял. События тут вообще не причем. Это я просто предоставил пример насчет координат, тут совсем разговор о другом.
Расширю пример : есть несколько стадий игры, начало, конец, в игре*. Некий объект меняет свои характеристики в течении цикла. И по окончанию игры нужно проводить действия. Все записало в модель, все держится, объектов куча поэтому проверяем в цикле. И вот к пример где мне пришлось делать 2 цикла с однотипными условиями так скажем :
1) Записали текущее состояние стола в модель
2) Проверяем в цикле - если хоть один объект *сделал что-то* - очищаем из модели тек. состояние
3) Проверяем в цикле - если хоть один объект *сделал что-то* - записываем то, что он сделал.
P.s. модель общая

Код AS3:

for(var i:int = 0; i < v.length; i++)
{
  if(v[i].isBetting) model.clear(); break;
}
for(var i:int = 0; i < v.length; i++)
{
  if(v[i].isBetting) model.arr.push(v[i].data);
}

Ну вот не нравится мне такая запись, из рассчета того, что можно и до 3х-4х циклов увеличить из за некоторых условий

AlexCooper 01.08.2013 16:34

Можно использовать временные хранилища ( так же и для остальных примеров, создаем временные массивы после цикла переприсвоение)
Код AS3:

var arr:Array = new Array();
for(var i:int = 0; i < v.length; i++)
{
  if(v[i].isBetting) {
      arr.push(v[i].data);
      model.clear();
  }
}
model.arr = arr; // or model.arr = model.arr.concat(arr);


expl 01.08.2013 17:31

Цитата:

Код AS3:

for(var i:int = 0; i < v.length; i++){
  if(v[i].isBetting) model.clear(); break;
}
for(var i:int = 0; i < v.length; i++)
{
  if(v[i].isBetting) model.arr.push(v[i].data);
}


Не уверен что понимаю, но суть проблемы в том, что дублирование "for(var i:int = 0; i < v.length; i++)" напрягает?
Кстати, почему сразу не писать:
Код AS3:

for each (var vi:V in v){
  if(vi.isBetting) model.clear(); break;
}
for each (var vi:V in v){
  if(vi.isBetting) model.arr.push(vi.data);
}

Если такую запись брать, то тут "for each (var vi:V in v)" == "пройтись по элементам v".
Тут нет никакой избыточной информации, короче не напишешь, и функции высших порядков тут лучше не сделают (можно, конечно, слепить массив функций-итераторов и упомянуть v только один раз - но это абзац и код короче не делает),
вы же кроме "пройтись по v" никакой логики не дублируете, или таки что-то есть ещё?
В чём проблема то?

in4core 03.08.2013 13:08

expl
Ну да именно напрягает несколько однотипных циклов в одном методе. И да форыч логичнее, просто писал на скорую руку

maxkar 03.08.2013 15:34

Да никак обычно в AS3 с этим не справляются. И проблема даже не столько в необходимости методов, сколько в очень длинном синтаксисе создания анонимных функций. Если бы не это, можно было бы писать в функциональном стиле:

Код AS3:

v.
  filter(function(item : Object, idx: int, array : Arr) : Boolean { return item.x > 30;}).
  forEach(function((item : Object, idx: int, array : Arr) : void { doSomething1(); });
 
if (v.some(function(item : Object, idx: int, array : Arr) : Boolean { return item.isBetting; }))
  model.clear();

Еще один пример с isBetting - это тоже filter+forEach.

Если создадите свою функцию, станет легче, но не сильно. Да, прототипы функций будут короче, но само объявление функции - длинное. Под платформу flash мне нечего вам посоветовать. Есть haxe, но там лямбды (анонимные функции) тоже начинаются со слова function.

А вот в функциональных языках все хорошо. Например, scala:
Код:

v.fiter(x => x.x > 30).forEach(y => doSomething1())
v.fiter(x => x.y > 40).forEach(y => doSomething2())
v.fiter(_.visible).forEach(y => doSomething3())
if (v.exists(_.isBetting))
  model.clear();
v.filter(_.isBetting).forEach(model.arr.push);

В других функциональных языках (вроде разновидностей ml и lisp'ов) все будет то же с точностью до синтаксиса/названия методов. Даже в haskell'е будет почти так же (ну с точностью до монад, конечно же).

expl 03.08.2013 22:18

forEach это уже по определению не _чисто_ функционально :) - без переменных ничего не сделаешь в отличие от функции reduce


Часовой пояс GMT +4, время: 08:31.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.