2010-11-02 20 views
6

J'ai unComment obtenir des caractères continus en C#?

List<String> MyList=new List<string>(); 

-je remplir la liste MyList avec n valeurs.

si la valeur de n est 2, alors la liste MyList contiendra

"A","B" 

si 10 puis

"A","B","C"....."J" 

si 30 puis

"A"....."Z","AA","AB",AC","AD" 

si 1000 puis

"A",....."Z","AA","AB"......"AZ","BA","BB"......."BZ"........"YZ","AAA",AAB"..... 
and so on 

Je ne sais pas comment faire.

S'il vous plaît aidez-moi à le faire en utilisant une méthode utilisant LINQ ou LAMBDA Expression

+0

Avez-vous besoin d'un CSV? Vous pouvez utiliser un stringbuilder et ajouter des valeurs n au lieu d'utiliser une liste . Ou voulez-vous convertir une liste existante de chaînes en csv? – pavanred

+0

@ Pavanred: Je ne pense pas que tout CSV est nécessaire ici - juste une liste de chaînes. –

+0

http://stackoverflow.com/questions/314466/generating-an-array-of-letters-in-the-alphabet-in-c – jjj

Répondre

6

Edit 2:

C'est probablement la façon de le mettre en œuvre plus facile. Je l'ai testé, ça marche bien. Vous pourriez générer un nombre infini de chaînes.

public IEnumerable<string> GenerateStrings() 
{ 
    foreach(string character in Alphabet()) 
    { 
     yield return character; 
    } 

    foreach (string prefix in GenerateStrings()) 
    { 
     foreach(string suffix in Alphabet()) 
     { 
     yield return prefix + suffix; 
     } 
    } 
} 

public IEnumerable<string> Alphabet() 
{ 
    for(int i = 0; i < 26; i++) 
    { 
     yield return ((char)('A' + i)).ToString(); 
    } 
} 

Stuff j'ai écrit avant:

Vous pouvez aussi écrire une petite fonction récursive qui retourne une chaîne par un certain indice. Ce n'est peut-être pas une performance optimale, car il y a des divisions répétitives, mais cela peut être assez rapide pour votre but.

Il est assez courte et facile:

string GetString(int index) 
{ 
    if (index < 26) 
    { 
    return ((char)('A' + index)).ToString(); 
    } 
    return GetString(index/26 - 1) + GetString(index % 26); 
} 
utilisation

(peut également être mis dans une autre méthode:.

List<string> strings = Enumerable.Range(0, 1000) 
    .Select(x => GetString(x)) 
    .ToList(); 

C'est le code de travail, vient d'écrire un test pour elle

Par exemple, l'application "full linq way" de GetString:

Editer:

public void IEnumerale<string> GenerateStrings() 
{ 
    int index = 0; 
    // generate "infinit" number of values ... 
    while (true) 
    { 
    // ignoring index == int.MaxValue 
    yield return GetString(index++); 
    } 
} 

List<string> strings = GenerateStrings().Take(1000).ToList(); 
+0

Bonne approche, bien que 'int i suffixCounter = 0;' ne compile pas, et vous n'utilisez pas 'i' ni' suffixCounter'. – Kobi

+0

@Kobi: merci, j'ai oublié de nettoyer cela. –

3

Ceci est similaire à this question (mais pas tout à fait assez pour marquer comme un double, et il est un problème difficile à rechercher de toute façon).

Utilisez l'une des IEnumerable<string> réponses de travail (ou au moins, tout ce qui couvre la gamme dont vous avez besoin), et si vous avez besoin pour créer une liste avec un certain nombre d'éléments, il suffit d'utiliser:

List<string> list = GenerateSequence().Take(count).ToList(); 
+1

Ce n'est pas vraiment une réponse à la question imo. –

+0

C'est un problème facile à rechercher si vous reconnaissez que c'est ce que fait Excel - essayez de chercher "excel colonne char" ou similaire. :-) – Ken

+4

@Stefan: En quoi n'est-ce pas une réponse à la question? Répondez à l'autre question, ajoutez la ligne supplémentaire, et vous avez terminé. Quel est le problème, précisément? –

3

Ce code fonctionne très bien, mais je ne suis pas sûr que ce soit "assez LINQ".

char[] validChars = Enumerable.Range(0, 26).Select(i => (char)('A' + i)).ToArray(); 
List<string> result = new List<string>(); 
List<string> generator = validChars.Select(ch => ch.ToString()).ToList(); 

int n = 1000; 

while (result.Count < n) 
{ 
    result.AddRange(generator); 
    generator = generator.Take((n - result.Count)/validChars.Length + 1) 
         .SelectMany(s => validChars.Select(ch => s + ch)) 
         .ToList(); 
} 

var output = result.Take(n); 
+0

Il passe directement de "AZ" à "ABC" et de "ABZ" à "ABCD". – Guffa

+0

@Guffa: c'est un bug, j'ai modifié mon code. Merci. –

+2

@Danny Chen: Maintenant cela fonctionne, mais ce n'est pas très efficace ... Il crée un demi-million de chaînes pour obtenir ces premiers milliers ... – Guffa

3

J'ai fait something similar dans SQL il y a un certain temps.

Traduit en C# Ceci est une fonction pour créer un code à partir d'un numéro:

public static string GetCode(int id) { 
    string code, chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    if (id <= chars.Length) { 
    code = chars.Substring(id - 1, 1); 
    } else { 
    id--; 
    int value = chars.Length, adder = 0; 
    while (id >= value * (chars.Length + 1) + adder) { 
     adder += value; 
     value *= chars.Length; 
    } 
    code = chars.Substring((id - adder)/value - 1, 1); 
    id = ((id - adder) % value); 
    while (value > 1) { 
     value /= chars.Length; 
     code += chars.Substring(id/value, 1); 
     id = id % value; 
    } 
    } 
    return code; 
} 

Ensuite, vous obtenez juste des nombres de 1 et, et traduisez en codes:

var codes = Enumerable.Range(1, 1000).Select(n => GetCode(n)); 

La limite de la fonction est actuellement "ZZZZZZ" ou 321272406. (Après que vous obtenez une division par zéro.)

Notez que cette fonction utilise toutes les combinaisons et renvoie "A" .. "Z", "AA" .. " ZZ "," AAA ".. "ZZZ" plutôt que de commencer par "AB" et "ABC".

0

@DannyChen c'est ça. votre code avec un peu de changements ..

char[] validChars = Enumerable.Range(0, 26).Select(i => (char)('A' + i)).ToArray(); 

int n = 30; 
int pointer = 0; 
int pointerSec = 0; 
int Deg = 0; 
string prefix = string.Empty; 
string prefixMore = string.Empty; 
List<string> result = new List<string>(); 

while (n > 0) 
{ 
    result.AddRange(validChars.Skip(pointer).Select(ch => prefix + ch).Take(n)); 
    if (pointer == 26) 
    { 
     pointer = -1; 
     Deg += 1; 
     prefixMore = "" + validChars[pointerSec]; 
     pointerSec++; 
     n++; 
    } 
    else 
    { 
     if (Deg == 0) 
     { 
      prefix = "" + validChars[pointer]; 
     } 
     else 
     { 
      prefix = prefixMore + validChars[pointer]; 
     } 
    } 
    n--; 
    pointer++; 
} 

c'est 100% correct.

+0

@Pramodh ... c'est ce que vous voulez ..! – jjj

1

Essayez le ..J'utilise Cross Rejoignez et une Union pour construire la source, puis filtrer le disque en utilisant le Prenez méthode d'extension

char[] charArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray(); 

List<String> MyList = new List<string>(); 
int n = 1000; 

         (from value1 in charArray 
         select new 
         { 
          newString = value1.ToString() 
         }) 
        .Union 
        (
         (from value1 in charArray 
         from value2 in charArray 

         select new 
         { 
          newString = string.Concat(value1, value2) 
         }) 
        ) 
        .Union 
        (
         (from value1 in charArray 
         from value2 in charArray 
         from value3 in charArray 

         select new 
         { 
          newString = string.Concat(value1, value2, value3) 
         }) 
        ) 
        .Take(n) 
        .ToList()       
        .ForEach(i => MyList.Add(i.newString)); 

Espérons que cela vous donnera une idée d'utiliser une combinaison de Linq, Lambda et méthode d'extension.