Форум 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=209412)

GrafMine 08.11.2014 03:00

проблема в рекурсии объекта
 
Добрый день, помогите решить такую головоломку через рекурсию :
Дан объект :
Код AS3:

{
  "main1":{
            "key1":{
              "key1.1":"text1","key1.2":"text2",...//могут быть еще объекты вместо простого стринга
            },
            "key2":{
            "key2.1":"text1","key2.2":"text2",...//могут быть еще объекты вместо простого стринга
            }
        },
        "main2":{
            "key1":{
              "key1.1":"text1","key1.2":"text2",...//могут быть еще объекты вместо простого стринга
            },
            "key2":{
            "key2.1":"text1","key2.2":"text2",...//могут быть еще объекты вместо простого стринга
            }
        }
}

в результате должно вывести в трейс :
Код AS3:

main1=key1key1.1=text1key1.2=text2main1=key2key2.1=text1key2.2=text2main2=key1key1.1=text1key1.2=text2main2=key2key2.1=text1key2.2=text2

Важен именно такой порядок и такая соедененность имен.

example:
Код AS3:

 
trace(recursion(obj))
 
function(obj):String{
//...
return string += key +"="+recursion(obj);
//...
}
 
output:
main1=key1key1.1=text1key1.2=text2main1=key2key2.1=text1key2.2=text2main2=key1key1.1=text1key1.2=text2main2=key2key2.1=text1key2.2=text2


silin 08.11.2014 11:04

Код AS3:

function objToSring(obj:Object):String
{
        var res:String = "";
        for ( var key:String in obj )
        {
                res += key + "=" + (objToSring(obj[key]) || obj[key]);
        }
        return res;
}

но вот с порядком имен никак, имхо - порядок будет непредсказуемым

КорДум 08.11.2014 12:10

Порядок сохранится только в массиве, обджект не linked в AS3 и порядок не хранит.

gloomyBrain 08.11.2014 12:31

КорДум прав, нужно сначала получить список ключей в объекте, потом их отсортировать и уже только после этого проводить трансляцию данных в строку.

GrafMine 08.11.2014 13:54

Да, с этим я как раз и столкнулся, это можно как-то написать не сильно громоздко ?

Добавлено через 1 час 4 минуты
Цитата:

Сообщение от silin (Сообщение 1174682)
Код AS3:

function objToSring(obj:Object):String
{
        var res:String = "";
        for ( var key:String in obj )
        {
                res += key + "=" + (objToSring(obj[key]) || obj[key]);
        }
        return res;
}

но вот с порядком имен никак, имхо - порядок будет непредсказуемым

Спасибо, ну логика построения строки не такая как я писал выше по вашему примеру вывело с учетом без сортировки так :
Код AS3:

//main2=key2=key2.2=text2key2.1=text1key1=key1.1=text1key1.2=text2main1=key2=key2.2=text2key2.1=text1key1=key1.1=text1key1.2=text2
а должно быть вот так :
//main2=key2key2.2=text2key2.1=text1main2=key1key1.1=text1key1.2=text2main1=key2key2.2=text2key2.1=text1main1=key1key1.1=text1key1.2=text2

я дошел до этого :

Код AS3:

package {
import flash.display.Sprite;
 
public class Recursion extends Sprite {
    public function Recursion() {
        var smtArray:Array = [{
            "main1": {
                "key1": {
                    "key1.1": "text1", "key1.2": "text2"
                },
                "key2": {
                    "key2.1": "text1", "key2.2": "text2"
                }
            },
            "main2": {
                "key1": {
                    "key1.1": "text1", "key1.2": "text2"
                },
                "key2": {
                    "key2.1": "text1", "key2.2": "text2"
                }
            }
        }];
        trace(convertToString(smtArray[0]));
    }
 
    private function convertToString(obj:*):String {
        var res:String = "";
 
        if(obj is Object){
            // получаем имена ключей с обьекта(хеш мапы)
            var namesHM:Array=[];
            for ( var key:String in obj ){
                namesHM.push(key);
            }
            namesHM.sort();//сортируем по имени
            for(var n:int=0; n<namesHM.length;n++){
                res += namesHM[n] +'='+convertToString(obj[namesHM[n]]);
            }
            return res;
        }else{//типа тут строка
            return obj;
        }
    }
}
}
 
output:
//main1=key1=key1.1=key1.2=key2=key2.1=key2.2=main2=key1=key1.1=key1.2=key2=key2.1=key2.2=

результат отсортирован ну логика построения строки не соответсвует, есть идеи ?

silin 08.11.2014 17:45

что-то такое может быть
Код AS3:

package {
        import flash.display.Sprite;
 
        public class Recursion extends Sprite {
                public function Recursion() {
                        var obj:Object =
                        {
                                "main1": {
                                        "key1": {
                                                "key1.1": "text1", "key1.2": "text2"
                                        },
                                        "key2": {
                                                "key2.1": "text1", "key2.2": "text2"
                                        }
                                },
                                "main2": {
                                        "key1": {
                                                "key1.1": "text1", "key1.2": {a:"a",b:"b"}
                                        },
                                        "key2": {
                                                "key2.1": "text1", "key2.2": "text2"
                                        }
                                }
                        }
 
 
 
                        res = "";
                        convertToString(obj);
                        trace( "res : " + res );
 
 
                }
 
 
                private var res:String = "";
                private function convertToString(obj:Object,pfx:String=""):void
                {
 
                        for ( var key:String in obj )
                        {
 
                                var subObj:* = obj[key];
                                if (subObj is String)
                                {
                                        res += pfx + key + "=" + subObj + "\n";
 
                                }else
                                {
                                        convertToString(obj[key], pfx + key);
 
                                }
 
                        }
 
                }
 
        }
}

Код:

а должно быть вот так :
//main2=key2key2.2=text2...

по какой логике между main2 и key2 есть '=', а между key2 и key2.2 - нет я не догнал, вставите сами где\если нужно

Dukobpa3 08.11.2014 18:55

Цитата:

Сообщение от silin
по какой логике между main2 и key2 есть '=', а между key2 и key2.2 - нет я не догнал

Первый вопрос который возник :)
Собственно в этом и сложность задачи.
Ключевое слово: "Второй уровень вложенности".
Подробнее объяснить сложно, сам с автором в скайпе уже полдня задачу решаю :)
Решили под тот вариант который в топике. Но недостаточно гибко. Когда закончим - поделимся :)

silin 08.11.2014 19:05

>>Ключевое слово: "Второй уровень вложенности".
ну я это и имел ввиду, если критерий известен, то втулить его - не вопрос как бы
Код AS3:

private function convertToString(obj:Object,pfx:String="",level:int=0):void
{
 
        for ( var key:String in obj )
        {
 
                var subObj:* = obj[key];
                if (subObj is String)
                {
                        res += pfx + key + "=" + subObj + "\n";
 
                }else
                {
                        var del:String = level == 1?"=":"";
                        convertToString(obj[key], pfx + del+key, level + 1);
 
                }
 
        }
 
}


Dukobpa3 08.11.2014 19:28

Нифига не тот результат.

Ваш вывод:
Код:

main2=key2key21=text1
main2=key2key22=text2
main2=key1key11=text1
main2=key1key12=text2
main1=key2key21=text1
main1=key2key22=text2
main1=key1key11=text1
main1=key1key12=text2

Ожидаемый.
Код:

main1=
        key1
                key11=text1
                key12=text2
main1=
        key2
                key21=text1
                key22=text2
               
main2=
        key1
                key11=text1
                key12=text2
main2=
        key2
                key21=text1
                key22=text2

Нигде никаких переносов строк не должно быть, расставил просто для понимания структуры.
Плюс ваш вариант не сортирует. Задача интереснее, чем на первый взгляд. Я тоже думал что за 15 минут накидаю и норм. Нифига.

GrafMine 08.11.2014 21:01

Вопрос решен , спасибо большое -> Dukobpa3
вот код :
Код AS3:

package {
    public class ObjectParser {
        public function ObjectParser() {
        }
 
        public static function sortKeys(obj:Object):Array {
            var result:Array = [];
            for (var key:String in obj) result.push(key);
            result.sort();
            return result;
        }
 
        public static function checkSecondLevel(obj:Object, sortedKeys:Array):Array {
            var result:Array = [];
            var key:String;
            var i:int;
 
            for (i = 0 ; i < sortedKeys.length ; i ++) {
                key = sortedKeys[i];
                result[i] = true;
 
                for each (var child:* in obj[key]) {
                    if (!(child is String)) {
                        result[i] = false;
                    }
                }
            }
            return result;
        }
 
        public static function apiObjToString(obj:Object):String {
            return objToSring(obj);
        }
 
        private static function objToSring(obj:Object, currKey:String = "", topKey:String = "", drawKey:Boolean = true):String {
            var res:String = "";
            var keys:Array = sortKeys(obj);
            var checkers:Array = checkSecondLevel(obj, keys);
            var key:String;
            var i:int;
 
            //trace(topKey + "/" + currKey + " -> " + keys + " -> " + checkers);
 
            for (i = 0 ; i < keys.length ; i ++) {
                key = keys[i];
 
                if (obj[key] is String) {
                    res += key + "=" + obj[key];
                } else {
                    res += objToSring(obj[key], key, currKey, checkers[i]);
                }
            }
 
            if (topKey == "" && currKey == "") {
                return res;
            } else {
                return (topKey != "" ? topKey + "=" : "")
                        + (topKey != "" || drawKey ? currKey : "")
                        + res;
            }
        }
    }
}

И тесты к коду :

Код AS3:

package {
    import org.flexunit.Assert;
 
 
    public class ObjectParserTest {
        public function ObjectParserTest() {
        }
 
        private var obj_first:Object = {
            main1: {
                key1: {
                    key11: "text1",
                    key12: "text2"
                }
            }
        };
        private var assert_first:String = "main1=key1key11=text1key12=text2";
 
        private var obj_second:Object = {
            main1: {
                key1: {
                    key11: "text1",
                    key12: "text2"
                },
                key2: {
                    key21: "text1",
                    key22: "text2"
                }
            }
        };
        private var assert_second:String = "main1=key1key11=text1key12=text2main1=key2key21=text1key22=text2";
 
        private var obj_full:Object = {
            main1: {
                key1: {
                    key11: "text1",
                    key12: "text2"
                },
                key2: {
                    key21: "text1",
                    key22: "text2"
                }
            },
            main2: {
                key1: {
                    key11: "text1",
                    key12: "text2"
                },
                key2: {
                    key21: "text1",
                    key22: "text2"
                }
            }
        };
        private var assert_full:String = "main1=key1key11=text1key12=text2main1=key2key21=text1key22=text2main2=key1key11=text1key12=text2main2=key2key21=text1key22=text2";
 
        private var obj_epic:Object = {
            main1: {
                key1: {
                    key11: "text1",
                    key12: "text2"
                },
                key2: {
                    key21: "text1",
                    key22: "text2"
                }
            },
            main2: {
                key1: {
                    key11: "text1",
                    key12: "text2",
                    key13: {
                        key131: "text1",
                        key132: "text2"
                    }
                },
                key2: {
                    key21: "text1",
                    key22: "text2"
                }
            },
            main3: {
                key1:"text1"
            }
        };
        private var assert_epic:String = "main1=key1key11=text1key12=text2main1=key2key21=text1key22=text2main2=key1key11=text1key12=text2key1=key13key131=text1key132=text2main2=key2key21=text1key22=text2main3key1=text1";
 
        [test]
        public function testCheckSecondLevel():void {
            var keys:Array = ObjectParser.sortKeys(obj_full);
            Assert.assertEquals(
                    JSON.stringify(ObjectParser.checkSecondLevel(obj_full, keys)),
                    JSON.stringify([false, false])
            );
 
            keys = ObjectParser.sortKeys(obj_second["main1"]);
            Assert.assertEquals(
                    JSON.stringify(ObjectParser.checkSecondLevel(obj_second["main1"], keys)),
                    JSON.stringify([true, true])
            );
 
            keys = ObjectParser.sortKeys(obj_full["main1"]);
            Assert.assertEquals(
                    JSON.stringify(ObjectParser.checkSecondLevel(obj_full["main1"], keys)),
                    JSON.stringify([true, true])
            );
        }
 
        [test]
        public function testSort():void {
            Assert.assertEquals(
                    JSON.stringify(ObjectParser.sortKeys(obj_full)),
                    JSON.stringify(["main1", "main2"])
            );
        }
 
        [test]
        public function testFirst():void {
            Assert.assertEquals(
                    ObjectParser.apiObjToString(obj_first),
                    assert_first
            );
        }
 
        [test]
        public function testSecond():void {
            Assert.assertEquals(
                    ObjectParser.apiObjToString(obj_second),
                    assert_second
            );
        }
 
        [test]
        public function testFull():void {
            Assert.assertEquals(
                    ObjectParser.apiObjToString(obj_full),
                    assert_full
            );
        }
 
        [test]
        public function testEpic():void {
            Assert.assertEquals(
                    ObjectParser.apiObjToString(obj_epic),
                    assert_epic
            );
        }
    }
}



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

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