0

ある種のソート優先度を使用して、カスタムの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()関数でこれが可能ですか?これを実用的/効率的な方法で解決する方法について、いくつかの指示が必要です。

前もって感謝します!

4

2 に答える 2

2

あなたはあなたの心の中で2つの問題を分離する必要があります。

1つは並べ替えです。比較可能なオブジェクトのリストを指定して、それらを「最低」から「最高」に並べ替えます。これは完全に解決された問題です。ご心配なく。

もう1つは比較です。2つのオブジェクトが与えられた場合、どちらが「最初」ですか?あなたが書いた仕様と、任意の2つのオブジェクトAとBを考えると、-1(オブジェクトAが最初)、0(ソートの目的で同等)、または1(オブジェクトBが最初)と言うことができます。

その関数を(お気に入りの言語で)記述し、それを言語の組み込みのソートライブラリに渡して、高速ソートを取得します。

于 2012-11-14T20:54:45.450 に答える
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のスターターです。それはあなたを正しい方向に向けるべきです。

まず、並べ替えの1つのレイヤーを処理する再帰的な並べ替え関数を作成し、次に子レイヤーがあるかどうかを確認するか、次を返します。

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

最後に、オブジェクトに子の並べ替え要件があるかどうかを確認します。これは実際には機能しません。最初のアイテムに子の並べ替えがあることを想定しているだけです。また、私が(sortingObject[0])のように、インデックスによってオブジェクトの変数にアクセスできることも100%ではありません(ただし、それらを確実に繰り返すことができます)。

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

AS3については、文字列で変数にアクセスするためのas3の変数名の文字列表現の取得を具体的に参照してください。あなたが何か他のことでそれをしたいのであれば、あなたはまたあなたの言語が熟考する必要があるでしょう

于 2012-11-14T22:39:46.543 に答える