2009-05-29 9 views
5

Sto cercando di creare una funzione che mi fornirà la posizione dell'alfabeto quando viene passato un indice. Sarà uguale al modo in cui Excel mostra le sue colonne. A ... Z, AA, AB .... ho scritto la funzione qui sotto per ottenere i risultati FINO Z. assomigliaAlfabeti di incremento

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 
    if (index <= alphabetsCount) 
    { 
     int code = (index - 1) + (int)'A'; 
     return char.ConvertFromUtf32(code); 
    } 
    return string.Empty; 
} 

Questo funziona bene fino a quando 'Z'. Restituisce "A" se passo 1 e restituisco "B" se passo 2 e così via. Ma, non sono in grado di capire come otterrò AA quando passo 27 a questa funzione. Credo di aver bisogno di un metodo ricorsivo per trovarlo.

Qualsiasi input per questo problema sarà fantastico!

Modifica

Ciò è suggerito da Tordek. Ma il suo codice fallirà in numeri come 52, 78 ecc. Aggiunta soluzione alternativa per questo ed ecco il codice di lavoro finale.

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 

    if (index > alphabetsCount) 
    { 
     int mod = index % alphabetsCount; 
     int columnIndex = index/alphabetsCount; 

     // if mod is 0 (clearly divisible) we reached end of one combination. Something like AZ 
     if (mod == 0) 
     { 
      // reducing column index as index/alphabetsCount will give the next value and we will miss one column. 
      columnIndex -= 1; 
      // passing 0 to the function will return character '@' which is invalid 
      // mod should be the alphabets count. So it takes the last char in the alphabet. 
      mod = alphabetsCount; 
     } 
     return GetColumnName(columnIndex) + GetColumnName(mod); 
    } 
    else 
    { 
     int code = (index - 1) + (int)'A'; 
     return char.ConvertFromUtf32(code); 
    } 
} 

risposta

4

Qualsiasi funzione ricorsiva può essere convertita in una iterativa equivalente. Trovo sempre facile pensare ricorsivamente prima:

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 

    if (index > alphabetsCount) { 
     return GetColumnName(index/alphabetsCount) + GetColumnName(index % alphabetsCount); 
    } else { 
     int code = (index - 1) + (int)'A'; 
     return char.ConvertFromUtf32(code); 
    } 
} 

che può essere convertito in semplice:

static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 
    string result = string.Empty; 

    while (index > 0) { 
     result = char.ConvertFromUtf32(64 + (index % alphabetsCount)) + result; 
     index /= alphabetsCount; 
    } 

    return result; 
} 

Anche così, ascoltare Joel.

+0

Grande.La mia matematica è arrugginita. Quindi non riuscivo a capire il funzionamento del modulo. Grazie per il codice. –

0

ricorsione è una possibilità - se index > 26, avete a che fare con index % 26 nel presente invito e concatenare in una chiamata ricorsiva su index/26. Tuttavia, l'iterazione è spesso più rapida e difficile da organizzare per casi semplici come questo. In pseudocodice:

string result = <convert `index % 26`> 
while index > 26: 
    index = index/26 
    result = <convert `index % 26`> + result 
return result 

o simile.

+0

Non c'è niente di sbagliato con il pseudocodice, ma è importante sapere che probabilmente si dovrebbe utilizzare la classe StringBuilder se si sta andando ad essere accodando una stringa in un ciclo, di risparmiare sulle assegnazioni degli oggetti: http://msdn.microsoft.com/en-us/library/system.text.stringbuilder(loband).aspx –

+0

Questo è sbagliato perché non è un sistema di base 26. Se A fosse 0, A sarebbe uguale a AA (0 == 00). Se A fosse 1, passare da Z ad AA sarebbe come andare da 9 a 11. –

+0

Paul, StringBuilder è eccessivo. Un int a 32 bit è 2^32 e 26^7 lo supera in modo che il massimo sia lungo 7 lettere. 7 iterazioni sono difficilmente tassabili. Una lunghezza di 64 bit avrebbe solo 14 lettere. :) –

0
 
static string GetColumnName(int index) 
{ 
    const int alphabetsCount = 26; 
    string result = ''; 

    if (index >= alphabetsCount) 
    { 
     result += GetColumnName(index-alphabetsCount) 
    } 
    return (string) (64 + index); 
} 

Il mio C# è ORRIBILE E RUGGENTE. Interpretalo come uno pseudocodice: quasi certamente non verrà compilato, ma potrebbe farti iniziare.

-1

Non voglio rispondere alla domanda in C# ma ho intenzione di mostrarvi quanto sia facile questo in Haskell.

alphas :: [String] 
alphas = [x ++ [c] | x <- ([]:alphas), c <- ['A'..'Z']] 

Prelude> take 100 alphas 
["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","AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK", 
"AL","AM","AN","AO","AP","AQ","AR","AS","AT","AU","AV","AW","AX","AY","AZ","BA", 
"BB","BC","BD","BE","BF","BG","BH","BI","BJ","BK","BL","BM","BN","BO","BP","BQ", 
"BR","BS","BT","BU","BV","BW","BX","BY","BZ","CA","CB","CC","CD","CE","CF","CG", 
"CH","CI","CJ","CK","CL","CM","CN","CO","CP","CQ","CR","CS","CT","CU","CV"]