sortOn具有优先级的功能

时间:2012-11-14 20:42:15

标签: java javascript algorithm actionscript-3 sorting

我想知道如何使用某种排序优先级创建自定义sortOn函数。我有一个更复杂的案例,但我主要想知道如何构建好的排序函数。

假设我有这个未分类的数据对象列表:

var myList = [
 {drink: {amount: 1, name: "cola"}}, 
 {drink: {amount: 5, name: "beer"}}, 
 {food: {amount: 7, name: "cake"}}, 
 {drink: {amount: 3, name: "fanta"}}, 
 {drink: {amount: 4, name: "tea}}, 
 {other: {amount: 1, name: "table"}}, 
 {food: {amount: 4, name: "mars"}},
 {food: {amount: 5, name: "pizza"}}, 
 {food: {amount: 4, name: "cake"}}, 
 {other: {amount: 12, name: "chair"}}, 
 {food: {amount: 14, name: "chips"}},
 {drink: {amount: 6, name: "coffee}}, 
 {food: {amount: 8, name: "chips"}}, 
 {food: {amount: 6, name: "pizza"}}, 
 {food: {amount: 1, name: "food"}} 
]

好的,想要使用以下规则进行排序:

first: sort in this order: food, drinks, others (note, thats not alphabetical)
  then: sort on amount, BUT on food, pizza's + cakes must be on top

在理想情况下,它看起来像这样(手动创建):

var myList = [
 {food: {amount: 5, name: "pizza"}},
 {food: {amount: 6, name: "pizza"}},
 {food: {amount: 4, name: "cake"}}, 
 {food: {amount: 7, name: "cake"}}, 
 {food: {amount: 1, name: "food"}}, 
 {food: {amount: 4, name: "mars"}}, 
 {food: {amount: 8, name: "chips"}}, 
 {food: {amount: 14, name: "chips"}},
 {drink: {amount: 1, name: "cola"}}, 
 {drink: {amount: 3, name: "fanta"}}, 
 {drink: {amount: 4, name: "tea}}, 
 {drink: {amount: 5, name: "beer"}}, 
 {drink: {amount: 6, name: "coffee}}, 
 {other: {amount: 1, name: "table"}}, 
 {other: {amount: 12, name: "chair"}}
]

同样,这完全不是一个真实世界的例子,但我有一些案例(甚至更深的嵌套对象),我想应用这些规则。

是否可以创建一些排序顺序查找列表(类似这样),或者这是不可行的?

priorityList = [
              food:[
                 name:["pizza", "tea", rest], 
                 amount: Array.ASCENDING}
                ], 
              drink, 
              other
          ]; // etc..

我想学习如何制作这种排序功能。我喜欢看Javascript或Actionscript解决方案,但其他语言也可以。有这个图书馆吗?我是否必须遍历所有项目,创建条件,在案例中推送/取消移位或使用自定义sort()功能吗?我需要一些指导如何以实用/有效的方式解决这个问题。

提前致谢!

2 个答案:

答案 0 :(得分:2)

你需要在脑海中分开这两个问题。

一个是排序:给出一个可比对象列表,从"最低"中排序。最高的"这是一个完全解决的问题。别担心。

另一个是比较:给定两个对象,即#34;第一个"?鉴于您编写的规范,以及任何两个对象A和B,您可以说-1(对象A是第一个),0(它们等同于排序目的)或1(对象B是第一个)。 / p>

编写该函数(用您最喜欢的语言)并将其传递给语言的内置排序库,以便快速排序。

答案 1 :(得分:1)

你是对的,你必须返回-1,0或1,但这并不意味着你无法处理它内部的复杂排序,虽然它意味着你必须自定义代码你遇到的每一个案例。像这样的东西会起作用:

function myCustomSort(firstObject, secondObject):int 
{
    // Is firstObject a food and the second not? firstObject goes in front. 
    // Are both objects a food?
        // Is firstObject's name pizza and the second not? 
        // firstObject goes in front. 
        //Are both objects' names pizza? Return 0 - they're equivalent.
    //ETC.
}

理想情况下,您希望支持类似您所提供的架构的示例。我建议在根目录中使结构与在子结构中相同(因此您可以在每个级别上运行相同的代码),您的示例将如下所示:

priorityList = {
                    "consumingType":[
                      "food":{
                         "name":[
                            "pizza", 
                            "tea"
                            ], 
                         amount: Array.ASCENDING
                        }, 
                      "drink", 
                      "other"
                    ], 
                    amount: Array.ASCENDING
                };   

实际解决方案可能略有不同,具体取决于实际结构(无论您的数据是JSON还是对象)和什么语言 - 但这里是AS3 的入门者,我还没有测试过;这应该指向正确的方向。

首先,我会编写一个递归排序函数来处理排序的一层,然后检查是否有子图层或返回:

function handleComplexSorting( sortingObject, first, second ) {
    var result:int = 0;
    //Extracting the property name of first/second will differ, 
    //but pretty sure this is how you do it in AS3.
    var firstValue:int = findSortValueForProperty(first[0], sortingObject[0]);
    var secondValue:int = findSortValueForProperty(second[0], sortingObject[0]);

    if( firstValue > secondValue ) {
        //firstValue should go first.
        result = -1;
    }
    else if(firstValue < secondValue){
        //secondValue should go first.
        result = 1;
    }
    else {//equal
        var childSortingObject:Object;
        if( hasChildSorting(sortingObject, childSortingObject) ){
            //return result of recursion
            result = handleComplexSorting(childSortingObject, first, second);
        }
        else {
            result = 0;
        }
    }
    return result;
}

findSortValueForProperty函数将是你添加升序/降序的地方,我把它遗漏了,但你只需要检查哪一个并反转结果值。这里的值由数组中其索引的倒数确定(首先出现的值最高,最后一个出现最低值,而不是 - 0值)。

function findSortValueForProperty(property:String, priorityProperties:Array):int {
    var resultValue:int = 0;
    var index = 0;
    for each( var currentProperty:String in priorityProperties ) {
        if(property == currentProperty) {
            resultValue = priorityProperties.length - index;
            break;
        }
        ++index;
    }
    return resultValue;
}

最后,检查对象是否有子排序要求。这实际上是行不通的,它只期望第一项可能有子排序。我也不是100%你可以通过索引来访问Object的变量,就像我(sortingObject[0])(你绝对可以迭代它们)。

function hasChildSorting(sortingObject:Object, outChild:Object):Boolean {
    var result:Boolean = false;
        if( sortingObject[0] is Object ) {
            result = true;
            outChild = sortingObject[0];
        }
    }
    return result;
}

对于AS3,请参见get string representation of a variable name in as3以按字符串访问变量。 如果你想用其他东西做这件事,你还需要你的语言reflection