В AS3 / Flex как я могу получить от плоских данных до иерархических данных? - PullRequest
0 голосов
/ 24 декабря 2010

У меня есть некоторые данные, которые извлекаются из базы данных и сопоставляются с коллекцией массивов.У этих данных есть поле с именем parentid, и я хотел бы отобразить данные в новую коллекцию массивов с иерархической информацией, чтобы затем передать их в расширенную сетку данных.добавить новое свойство / поле / переменную типа ArrayCollection с именем children, а затем удалить дочерний объект из исходного списка и клонировать его в массив children?Любая помощь будет принята с благодарностью, и я заранее прошу прощения за этот код:

private function PutChildrenWithParents(accountData : ArrayCollection) : ArrayCollection{
    var pos_inner:int = 0;
    var pos_outer:int = 0;
    while(pos_outer < accountData.length){
        if (accountData[pos_outer].ParentId != null){
            pos_inner = 0;
            while(pos_inner < accountData.length){
                if (accountData[pos_inner].Id == accountData[pos_outer].ParentId){
                    accountData.addItemAt(
                        accountData[pos_inner] + {children:new ArrayCollection(accountData[pos_outer])}, 
                        pos_inner
                    );
                    accountData.removeItemAt(pos_outer);
                    accountData.removeItemAt(pos_inner+1);
                }
                pos_inner++;
            }
        }
        pos_outer++;
    }
    return accountData;                 
}

Ответы [ 3 ]

2 голосов
/ 04 апреля 2011

У меня была похожая проблема с иерархическим набором задач, который немного отличался, так как в нем много корневых элементов, это то, что я сделал, мне кажется хорошим:

public static function convertFlatTasks(tasks:Array):Array
    {
        var rootItems:Array         = [];
        var task:TaskData;

        // hashify tasks on id and clear all pre existing children
        var taskIdHash:Array        = [];           
        for each (task in tasks){
            taskIdHash[task.id]     = task;
            task.children           = [];
            task.originalChildren   = [];
        }

        // loop through all tasks and push items into their parent
        for each (task in tasks){
            var parent:TaskData     = taskIdHash[task.parentId];

            // if no parent then root element, i.e push into the return Array
            if (parent == null){
                rootItems.push(task);
            }
            // if has parent push into children and originalChildren
            else {
                parent.children.push(task);
                parent.originalChildren.push(task);
            }
        }

        return rootItems;
    }
0 голосов
/ 25 декабря 2010

Вот что я в итоге сделал, по-видимому, вы можете динамически добавлять новые свойства к объекту с помощью

    object['new_prop'] = whatever

Оттуда я использовал рекурсивную функцию для итерации любых дочерних элементов, чтобы вы могли иметь n уровней иерархии, и, если он обнаружит что-либо, он будет проходить по цепочке по ссылке, пока исходная функция не найдет его и не выполнит над ним действие.

private function PutChildrenWithParents(accountData : ArrayCollection) : ArrayCollection{
    var pos_inner:int = 0;
    var pos_outer:int = 0;
    var result:Object = new Object(); 
    while(pos_outer < accountData.length){
        if (accountData[pos_outer].ParentId != null){
            pos_inner = 0;
            while(pos_inner < accountData.length){
                result = CheckForParent(accountData[pos_inner],
                                        accountData[pos_outer].ParentId);   
                if (    result != null    ){
                    if(result.hasOwnProperty('children') == false){
                        result['children'] = new ArrayCollection();
                    }
                    result.children.addItem(accountData[pos_outer]);
                    accountData.removeItemAt(pos_outer);
                    pos_inner--;
                }
                pos_inner++;
            }
        }
        pos_outer++;
    }
 return accountData;
}

private function CheckForParent(suspectedParent:Object, parentId:String) : Object{
    var parentObj:Object;
    var counter:int = 0;
    if ( suspectedParent.hasOwnProperty('children') == true ){
        while (counter < suspectedParent.children.length){
        parentObj = CheckForParent(suspectedParent.children[counter], parentId);
        if (parentObj != null){ 
            return parentObj;
                }
            counter++;
        }
    }
    if ( suspectedParent.Id == parentId ){
        return suspectedParent;
    }
    return null;
}
0 голосов
/ 24 декабря 2010

Попробуйте:

AccountData:

public class AccountData 
{
    public var Id:int;
    public var ParentId:int;

    public var children:/*AccountData*/Array;

    public function AccountData(id:int, parentId:int) 
    {
        children = [];

        this.Id = id;
        this.ParentId = parentId;
    }

}

Код:

private function PutChildrenWithParents(accountData:ArrayCollection):AccountData
{
    // dummy data for testing
    //var arr:/*AccountData*/Array = [new AccountData(2, 1), 
    //  new AccountData(1, 0), // root
    //  new AccountData(4, 2),
    //  new AccountData(3, 1)
    //  ];

    var arr:/*AccountData*/Array = accountData.source;

    var dict:Object = { };          
    var i:int;

    // generate a lookup dictionary
    for (i = 0; i < arr.length; i++)
    {
        dict[arr[i].Id] = arr[i];
    }

    // root element
    dict[0] = new AccountData(0, 0);

    // generate the tree
    for (i = 0; i < arr.length; i++)
    {   
        dict[arr[i].ParentId].children.push(arr[i]);
    }
    return dict[0];
}

dict[0] теперь содержит ваш корневой элемент.

Возможноу него не самая лучшая производительность, но он делает то, что вы хотите.

PS: этот код предполагает отсутствие недопустимых идентификаторов ParentId.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...