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 指出的那样,这不适用于基数 36,因为此函数使用的最高基数是 16。我将把它留给其他有类似问题且基数较小的人,但你最好使用其中一个其他解决方案。太糟糕了,因为这会很光滑......

于 2010-10-19T20:32:43.363 回答