5

base36 (0-9 から az) で編成されたフォルダーのリストがあります。現在、それらを読み取るための私の現在の実装は、数値を反復処理し、base32 に変換し、フォルダーが存在するかどうかを確認することです。終了しない場合はデータを読み取ります。

ここでの問題は、フォルダーの番号にギャップがあることです。例: 0,1,2,4,5,6,8,a,b,c,g,k,p

それらすべてを正しい順序で反復処理する最良の方法は何でしょうか(任意の数のフォルダーが存在する可能性があることを考慮して)?

(注:ディレクトリはアルファベット順に並べられるため、すべてのディレクトリを単純に取得することはできません。たとえば、2Aはzの前に配置されます)

4

3 に答える 3

5

すべての可能な値を順番に推測するものを作成しようとするのではなく、おそらくすべてのディレクトリをメモリに取得してから並べ替えるでしょう。

var names = GetAllDirectoryNames();
names.Sort(CompareNames);
foreach( var name in Names)
{
  DoSomethingWithDir(name);
}

//...

private static int CompareNames(string x, string y)
{
  if( x == null && y == null) return 0;
  if( x== null) return -1;
  if( y == null) return 1;

  var xVal = Base36Decode(x);
  var yVal = Base36Decode(y);
  if( xVal > yVal) return 1;
  if( xVal < yVal) return -1;
  return 0;
}

private long Base36Decode(string inputString)
{
    var charList = "0123456789abcdefghijklmnopqrstuvwxyz";

    inputString = Reverse(inputString.ToLower());
    long result = 0;
    int position = 0;
    foreach (char c in inputString)
    {
        result += charList.IndexOf(c) * (long)Math.Pow(36, position);
        position++;
    }
    return result;
}
于 2010-10-19T20:32:02.097 に答える
3

これは事実上、フォルダー名の基数ソートです。最初にすべてをアルファベット順に並べ替えてから、文字列の長さで並べ替えます。

var names = new[] {"4cc", "2a", "0", "z", "1ab"};

foreach (var n in names.OrderBy(x => x).OrderBy(y => y.Length)) 
{
    Console.WriteLine(n);
}

収量:

0
z
2a
1ab
4cc
于 2010-10-19T20:31:38.100 に答える
1

これを試して、それらを順番に取得してください:

List<string> b36Items = new List<string>;
//Load with base 36 strings;

List<string> sortedItems = b36Items.OrderBy( t=> Convert.ToInt32(t,36)).ToList();

Convert.ToInt32(string, base)のドキュメントはこちら。

アップデート

@Philip Rieckが指摘したように、この関数が機能する最高の基数は16であるため、これは基数36では機能しません。より小さな基数で同様の問題を抱えている他の人のために残しますが、次のいずれかを使用することをお勧めします他のソリューション。これはかなり滑らかだったので残念です...

于 2010-10-19T20:32:43.363 に答える