Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Выявление отличий одного Object`а от другого?! (http://www.flasher.ru/forum/showthread.php?t=178232)

ERrorMAKros 17.04.2012 22:49

Выявление отличий одного Object`а от другого?!
 
Доброе время суток,

...родился следующий вопрос:
Не поделится ли кто рабочей функцией, которая сравнивала два Object`а
и отображала на выходе их разницу.

Код AS3:

var objOriginal:Object = {
  a: "a",
  b: "1",
  c: {
      sub1: false,
      sub2: {
        x:10,
        y:20,
        z:null
      }
  }
}
 
var objChanged:Object = {
  a: "a",
  b: "2",
  c: {
      sub1: false,
      sub2: {
        x:10,
        y:20,
        z:{
            z_param: [1,2,3,4, "last"]
        }
      }
  }
}
 
var objResult:Object = theSuperFunction(objOriginal, objChanged);
 
// OUTPUT
objResult == {
  b:2,
  c:{
      sub2:{
        z:{
            z_param: [1,2,3,4, "last"]
        }
      }
  }
}

т.е. результатом выполнения функции является object содержащий в себе только измененные параметры и их новые значения.
Ни у кого случаем нет такой на вооружение?

strangedk 17.04.2012 23:11

Я думаю что не нужно конструировать универсальный метод. Это явно не пойдет на пользу.

Куда лучше использовать типизированные объекты, и соответствующие методы сравнения.

ERrorMAKros 17.04.2012 23:16

Моя необходимость в "такой" функции в следующем:

1. У меня есть Object модель данных;
2. На протяжении работы приложения модель терпит изменения;
3. В результате работы приложения я хочу видеть только измененные участки модели;

strangedk 17.04.2012 23:18

Всё равно направлю в ту же степь: Создайте типизированный объект, и с помощью getter/setter следите за тем что изменилось.

Добавлено через 1 минуту
Если ваша "модель" действительно модель, то можете вообще объявить её синглтоном.

Psycho Tiger 17.04.2012 23:21

Разомнул мозги.
Метод может не создавать полные копии объектов в объектах, если в оригинале он null - просто пишет в результирующий объект ссылку.

Код AS3:

package {
        import artshlagin.utils.Tracer;
        import flash.display.Sprite;
        import flash.events.Event;
 
        /**
        * ...
        * @author Artem Shlagin
        */

        public class Main extends Sprite {
 
                public function Main():void {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        var objOriginal:Object = {
                          a: "a",
                          b: "1",
                          c: {
                                  sub1: false,
                                  sub2: {
                                        x:10,
                                        y:20,
                                        z:null
                                  }
                          }
                        }
 
                        var objChanged:Object = {
                          a: "a",
                          b: "2",
                          c: {
                                  sub1: false,
                                  sub2: {
                                        x:10,
                                        y:20,
                                        z:{
                                                z_param: [1,2,3,4, "last"]
                                        }
                                  }
                          }
                        }
                        var objResult:Object = theSuperFunction(objOriginal, objChanged);
                        Tracer.fullTraceObject(objResult);
 
                }
 
                private function theSuperFunction(objOriginal:Object, objChanged:Object):Object {
                        var result:Object = { };
                        if (!objOriginal) return objChanged;
                        for (var name:String in objOriginal) {
                                if (!(name in objChanged)) continue;
                                if (isComposite(objOriginal[name])) {
                                        if (!isComposite(objChanged[name])) result[name] = objChanged[name];
                                        else{
                                                var temp:Object = theSuperFunction(objOriginal[name], objChanged[name]);
                                                if (!isEmpty(temp)) result[name] = temp;
                                        }
                                }
                                else {
                                        if (objChanged[name] !== objOriginal[name]) result[name] = objChanged[name];
                                }
                        }
                        return result;
                }
 
                /**
                * Что-то не пришло в голову лучшего способа проверки на хэш
                * @param        object
                * @return
                */

                private function isComposite(object:*):Boolean {
                        return typeof object === "object";
                }
                private function isEmpty(temp:Object):Boolean {
                        for (var name:String in temp) {
                                return false;
                        }
                        return true;
                }
 
 
 
        }
 
}

Код трейсера:
Код AS3:

package artshlagin.utils
{
        /**
        * ...
        * @author Artem Shlagin
        */

        public class Tracer
        {
                public static var traceFunction:Function = trace;
                public static var nameDelimiter:String = " => ";
                public function Tracer()
                {
                        throw new Error("Class is static");
                }
 
                public static function fullTraceObject(object:Object):void {
                        recoursiveTrace(object);
                }
 
                private static function recoursiveTrace(o:Object, startValue:int = 0):void {
                        for (var name:Object in o)
                        {
                                var otst:String = "";
                                if (startValue > 0) {
                                        var i:int = startValue;
                                        while (i--) otst += "    ";
                                }
                                traceFunction.call(null, otst + name + nameDelimiter + o[name]);
                                if ((typeof o[name]) === "object") recoursiveTrace(o[name], startValue+1);
                        }
 
                }
 
        }
}

Результат:
Код:

b => 2
c => [object Object]
    sub2 => [object Object]
          z => [object Object]
              z_param => 1,2,3,4,last
                    0 => 1
                    1 => 2
                    2 => 3
                    3 => 4
                    4 => last

Но не ручаюсь за правильность работы во всех ситуациях.

ERrorMAKros 17.04.2012 23:22

Это не просто, на самом деле там очень широкая и динамичная иерархия объектов, они сами по себе вносят изменения напрямую в модель (каждый в свою ветку), многие объекты даже не могут иметь геттеры/сеттеры потому что являются частью swc и финализированных классов. Так что тут без вариантов )

Добавлено через 24 минуты
Psycho Tiger, спасибо за код - пригодился!


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

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