在AS3 / Flex中,如何从平面数据到分层数据?

时间:2010-12-23 21:16:16

标签: flex flash actionscript-3

我有一些数据被从数据库中拉出并映射到数组收集。这个数据有一个名为parentid的字段,我想将数据映射到一个带有分层信息的新数组集合,然后输入到高级数据网格。

我想我基本上试图获取父对象,添加一个名为children的ArrayCollection类型的新属性/字段/变量,然后从原始列表中删除子对象并将其克隆到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 个答案:

答案 0 :(得分:2)

我有一个类似的问题,分层任务集略有不同,因为它有很多根元素,这就是我做的,对我来说似乎很好:

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;
    }

答案 1 :(得分:0)

试试这个:

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。

答案 2 :(得分:0)

这是我最终做的事情,显然你可以使用

动态地向对象添加新属性
    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;
}