2

16進数で0からFまで数えるのと同じように、「数えたい」数字と文字の配列があります...そして最大値に達したときに、「数十」で最初からやり直したいと思います。 " 桁。

これは、Azure Tableのストレージ効率を高め、PrimaryKeysを小さく保つために必要です(tinyURLで使用できるようにするため)。最初に、ここに記載されているように、これらの文字のみがpropertyNameとして許可されていることを考慮してください。以下の配列では、各文字はAzureによる並べ替え方法に従って配置されています。

  public static string[] AzureChars = new string[]
   {
        "0","1","2","3","4","5","6","7","8","9","A",
        "B","C","D","E","F","G","H","I",
        "J","K","L","M","N","O","P","Q",
        "R","S","T","U","V","W","X","Y",
        "Z","a","b","c","d","e","f","g",
        "h","i","j","k","l","m","n","o",
        "p","q","r","s","t","u","v","w",
        "x","y","z"       
   };

私の目標は、2つの文字列/ ASCII文字を使用して、文字列「00」から小文字の「zz」までカウントすることです。

C#を使用してこの概念にアプローチするための最良の方法は何ですか?
-配列は使用する正しいオブジェクトですか?
-特定の文字(大文字の「Y」)を配列内のその位置に関連付けるにはどうすればよいですか?

私はこのアイデアを試しているところです。一見良いブラシのように見えますが、このようにやろうと考えている人は誰もいません。どう思いますか?

4

3 に答える 3

3

あなたの質問は、実際には、数値を2桁の62進数に変換することについてです。正の数を任意の底に変換するための一般的なコードスニペットを次に示します。

var n = 1234;
var baseNumber = 62;
var numberOfDigits = 2;
var digits = new Int32[numberOfDigits];
for (var i = 0; i < digits.Length; i += 1) {
  digits[i] = n%baseNumber;
  n /= baseNumber;
}

数字を文字にマップする必要があり、ルックアップテーブルまたはそれを行うための小さな関数が適しています。

可変桁数を持つという追加機能に関する特定の問題については、次のコードを記述します。

var n = 123456; 
var digitCount = 3;
var digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var number = String.Empty;
for (var i = 0; i < digitCount; ++i) {
  number = digits[n%digits.Length] + number;
  n /= digits.Length;
}

このコードは、などに変換されることに注意してください。しかし0、実際にはそれが必要だと思います。0001001

元に戻すには、次のコードを使用できます。

var n = 0;
for (var i = 0; i < number.Length; ++i)
  n = n*digits.Length + digits.IndexOf(number[i]);

これString.IndexOf()は変換を行うための最も効率的な方法ではありませんが、ほとんどの場合は問題ありません。

元の数値がベース62の数値に格納できる最大の数値よりも大きい場合、逆変換すると異なる数値になることに注意してください。六十二進法の3桁の場合、元の数値が。以上の場合に当てはまりますzzz = 62^3 - 1 = 238327

于 2010-09-18T08:53:39.320 に答える
2

そのためのモジュラスを使用します(そして残りを取得します)

        int i = AzureChars.Length;
        int index = 62 //character to lookup;
        string a = AzureChars[index % i];

charのインデックスを取得します。

        int index = Array.IndexOf(AzureChars, "Y");

お気に入り:

        string text = "YY";
        int index1 = Array.IndexOf(AzureChars, text[1].ToString());
        int index2 = Array.IndexOf(AzureChars, text[0].ToString());

代わりに、CharArray(char [])を使用するか、次のような長い文字列を使用する必要があります。

 static string AzureChars= "012456789.....qrstuvwxyz";

それを明確にするためにすべて一緒に:

    static void Main(string[] args)
    {
        char[] b = AzureCharConverter.ToCharArray(522);
        int i = AzureCharConverter.ToInteger(b);
    }


    public static class AzureCharConverter
    {
         private static readonly string _azureChars
         = "012456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

         public static int ToInteger(string chars)
         {
                 int l = _azureChars.IndexOf(chars[0]);
                 int r = _azureChars.IndexOf(chars[1]);
                 return (l * _azureChars.Length) + r;
         }


         public static char[] ToCharArray(int value)
         {
                  char l = _azureChars[value / _azureChars.Length];
                  char r = _azureChars[value % _azureChars.Length];
                  return new char[] { l, r };
         }
    }

入力アルファが常に2桁であり、結果が常に3720未満である場合

于 2010-09-18T08:28:41.463 に答える
2

配列の要素はすべて単一の文字であるため、おそらく文字の配列として宣言できます。

public static char[] AzureChars = new char[]
{
    '0', '1', '2', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
    'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
    'v', 'w', 'x', 'y', 'z'       
};

これで、任意の文字列長nのすべてのn文字の文字列のセット全体を返す関数を簡単に作成できます。私のバージョンは再帰的です。長い文字列には遅すぎることがわかった場合は、おそらく最適化できます。

public static IEnumerable<string> AzureStrings(int desiredLength)
{
    if (desiredLength == 0)
        return new[] { "" };
    return AzureChars.SelectMany(ch => AzureStrings(desiredLength - 1)
                                       .Select(str => ch + str));
}

Skipこれで、とを使用してシーケンスの任意のチャンクを生成できますTake

// Prints “5v, 5w, 5x, 5y, 5z, 60, 61, 62, 64, 65”
Console.WriteLine(string.Join(", ", AzureStrings(2).Skip(300).Take(10)));
// Prints “3721”
Console.WriteLine(AzureStrings(2).Count());

これは何かを出力する前に最初の300要素を計算するという事実にもかかわらず、私にとっては十分に高速です。ここでのこのクレイジーな計算でさえ、1秒もかかりません。

// Prints “5PkS, 5PkT, 5PkU, 5PkV, 5PkW, 5PkX, 5PkY, 5PkZ, 5Pka, 5Pkb”
Console.WriteLine(string.Join(", ", AzureStrings(4).Skip(1000000).Take(10)));
于 2010-09-18T08:38:26.987 に答える