2009-06-24 26 views
1

これはしばらくの間私を悩ませていました。私はいくつかのアプローチを試みてきたが、どれも正しく働いていない。C#配列の並べ替え順序のカスタマイズ

私はIRCクライアントを作成しています。ユーザ名のリストを整理しようとしています(現在のチャンネルのユーザのアクセスレベルでソートする必要があります)。

これは簡単です。問題は、このリストは、ユーザーがチャンネルに参加するか退室するたびに追加する必要があるため、ユーザー名をリストから削除して、再結合時に正しい位置に再追加する必要があります。

各ユーザーのアクセスレベルは、各ユーザー名の先頭に1文字ずつ表示されます。これらの文字は予約されているため、シンボルの1つから始まる名前の潜在的な問題はありません。 (私はそれらをソートする必要があるために)最高から最低までの記号は以下のとおりです。〜 & % +

ユーザー@アクセスの任意の並べ替えなしに、ユーザー名の前に何のシンボルを持っていません。それらはリストの一番下になければなりません。例えば

:未ソート配列が含まれている可能性があり、以下: 〜USER1〜user84 @ user3に& USER8 + user39 user002 user2838%user29

そして要素は次の順序であるようにソートする必要があります を〜 user1〜user84 & user8 @ user3%user29 + user39 user002 user2838

ユーザーをアクセスレベル別にソートした後、アルファベット順にソートする必要があります。

誰かが私を助けることができたら、私は大変感謝しています。 ありがとうございます。

+0

どのようにユーザー名のリストを保存していますか?それがデータベースの場合は、リストに入れる前にSQLを使用して必要な順序でデータを取得できますか? – BarneyHDog

答えて

1

配列にオブジェクトが含まれている限り、オブジェクトにIComparableを実装してからArray.Sort()を呼び出します。

コレクションが変更可能な場合は、リスト<>を使用することをおすすめします。

+0

は、おそらく最高のは、非ジェネリックIComparableをするのではなくIComparableをを使用するか、またはOPがList <>を使用していた場合は、両方が – thecoop

+0

はい、IComparableをが良いでしょう実装するComparableををオフに継承するが、私は、この作品とは思わないしますIComparableを必要とするArray.Sort()に対して – stevehipwell

1

SortedList<K,V>は、IComparableインターフェイスを実装しているK(キー)を使用して、並べ替え基準を定義することができます。 Vは単にnullでも同じKオブジェクトでもかまいません。

+0

彼は値をソートしたいと思っていますが、キーはそうではありません...非常にラウンドアバウトの方法です。 –

+0

実際には、この場合キー==値です。すでにソートされたリストを持っている場合、要素を追加するたびにSort()を呼び出すことはかなり非効率的です。とにかく、よりクリーンなソリューションが必要な場合は、PowerCollectionsのOrderedSet (たとえばhttp://www.codeplex.com/PowerCollections)を使用できます。 –

1

IComparer<T>またはComparison<T>Array.Sortとすることができます。次に、自分で比較を実装するだけです。それが比較的複雑な比較(これはこれのように聞こえる)なら、私はIComparer<T>を別のクラスに実装すると簡単に単体テストできます。次に呼び出し:

Array.Sort(userNames, new UserNameComparer()); 

UserNameComparerは何の状態を持っていない場合は、便利なインスタンスが定義されているしたい場合があります:

Array.Sort(userNames, UserNameComparer.Instance); 

List<T>は、ソートのために同様のオプションを持っている - 私は個人的にではなく、リストを使用したいですあなたがアイテムを定期的に追加/削除しようとしている場合は、配列を返します。

実際、フルソートを行う必要はほとんどないようです。ユーザーを削除してもソート順は変わりません。挿入すると、正しいポイントに挿入するだけです。言い換えれば、次のものが必要です。

  • リストを作成し、ユーザーを削除するだけの簡単な操作
  • あるユーザーを追加すると、それらに
を挿入する場所を見つける必要が
  • で開始することを並べ替えます

    Array.BinarySearchまたはList.BinarySearchを使用して最後のステップを実行できます。この場合も、カスタムIComparer<T>を指定できます。ユーザーを挿入する場所を知ったら、これを比較的安価に行うことができます(コレクション全体を再度ソートするのに比べて)。

  • 0

    IComparerインターフェイス(またはそれはgeneric version)をご覧ください。 CompareToメソッドを実装するときは、2つのユーザー名のいずれかに予約文字が含まれているかどうかを確認します。どちらも特別な予約文字を持っていないか、または両方が同じ文字を持っている場合は、アルファベット順の並べ替えを処理するString.CompareToメソッドを呼び出します。それ以外の場合は、カスタムソートロジックを使用します。

    0

    私は、ソートのショットを与え、次仕分けのアプローチを思い付いた:

    List<char> levelChars = new List<char>(); 
    levelChars.AddRange("+%@&~".ToCharArray()); 
    List<string> names = new List<string>(); 
    names.AddRange(new[]{"~user1", "~user84", "@user3", "&user8", "+user39", "user002", "user2838", "%user29"}); 
    names.Sort((x,y) => 
           { 
            int xLevel = levelChars.IndexOf(x[0]); 
            int yLevel = levelChars.IndexOf(y[0]); 
    
            if (xLevel != yLevel) 
            { 
             // if xLevel is higher; x should come before y 
             return xLevel > yLevel ? -1 : 1; 
            } 
    
            // x and y have the same level; regular string comparison 
            // will do the job 
            return x.CompareTo(y);      
           }); 
    

    をこの比較コードは全く同じようにIComparer<T>実装のCompareメソッド内で生きることができます。

    関連する問題