Comment puis-je convertir un numéro à une coutume 2char BaseX et retour? (Aka: Comment faire Azure Table compression de la propriété)

StackOverflow https://stackoverflow.com/questions/3740865

Question

Dans le même dans la façon dont on compte de 0 à F Hex, j'ai un tableau de chiffres et de lettres que je veux « compter » de ... et quand je frappe la valeur maximale, je veux tout recommencer à la colonne "des dizaines".

Je en ai besoin pour augmenter l'efficacité du stockage dans le tableau Azure, et de garder mes PrimaryKeys minuscules (pour que je puisse les utiliser dans un tinyURL). Tout d'abord considérer que seuls ces caractères sont autorisés comme propertyName, comme documenté ici . Dans le tableau ci-dessous, chaque caractère est placé en fonction de Azure tri.

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

Mon but est d'utiliser 2 chaîne / caractères ASCII à compter de la chaîne « 00 » en minuscules « zz ».

Quelle est la meilleure façon d'aborder ce concept en utilisant C #?
- Est-ce un tableau l'objet correct d'utiliser
? - Comment puis-je associer un caractère donné (majuscule « Y ») avec la position de dans le tableau

Je suis juste expérimenter cette idée. Tout d'abord la brosse, il semble comme un bon, mais je n'ai pas vu quelqu'un envisager de faire les choses de cette façon. Que pensez-vous?

Était-ce utile?

La solution

question que vous est vraiment convertir un nombre en un nombre de base à deux chiffres 62. Voici un extrait générale de code pour convertir un nombre positif dans une base arbitraire:

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

Vous devez mapper les chiffres en caractères et une table de consultation ou une petite fonction pour faire cela est approprié.

Pour votre problème spécifique avec la fonction supplémentaire d'avoir un nombre variable de chiffres j'écrire ce code:

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

Notez que ce code vous permet de convertir 0 en 000, 1 en 001 etc., mais je pense que c'est en fait ce que vous voulez.

Pour reconvertir, vous pouvez utiliser ce code:

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

Le String.IndexOf() n'est pas la façon la plus efficace de faire la conversion, mais dans la plupart des cas devrait être OK.

Notez que si votre numéro d'origine est plus grand que le plus grand nombre qui peut être stocké dans votre numéro de base 62 le dos de conversion se traduira par un nombre différent. Pour 3 chiffres dans la base 62, cela est vrai si le nombre original est supérieure ou égale à zzz = 62^3 - 1 = 238327.

Autres conseils

Étant donné que les éléments de votre tableau sont tous les caractères simples, vous pouvez probablement déclarer comme un tableau de caractères:

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

Maintenant, vous pouvez facilement écrire une fonction qui retourne l'ensemble de tous les n chaînes -character pour une longueur de chaîne souhaitée n . Ma version est récursive; si vous trouvez qu'il est trop lent pour les chaînes oblongues, vous pouvez probablement l'optimiser:

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

Maintenant, nous pouvons générer une partie de la séquence en utilisant Skip et 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());

En dépit du fait que ce calcule les 300 premiers éléments avant la sortie quoi que ce soit, il est bien assez vite pour moi. Même ce calcul fou prend ici moins d'une seconde:

// Prints “5PkS, 5PkT, 5PkU, 5PkV, 5PkW, 5PkX, 5PkY, 5PkZ, 5Pka, 5Pkb”
Console.WriteLine(string.Join(", ", AzureStrings(4).Skip(1000000).Take(10)));

utiliser le module pour que (et obtenir le reste)

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

Retourne l'index d'un caractère:

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

comme:

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

peut-être vous devez utiliser un CharArray (char []) au lieu, ou tout simplement une longue chaîne comme:

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

tous ensemble à préciser:

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

à condition que l'alpha d'entrée est toujours de deux chiffres et le résultat est toujours inférieure à 3.720

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top