Je ne suis pas très expérimenté avec C # et j'ai pour tâche de développer un programme simple qui peut prendre deux paramètres; une chaîne et un entier. La chaîne doit être retournée, et l'entier est censé définir le nombre maximum de chaque caractère spécifique renvoyé dans la chaîne, c'est-à-dire:
input: "aaabbbbc", "2" output: aabbc
input: "acc", "1" output: ac
J'ai essayé de regarder différentes collections comme IEnumerator pour aider à rendre le code plus facile à écrire, mais comme je Je ne suis pas très expérimenté, je ne sais pas comment les utiliser.
Voici le code que j'ai écrit jusqu'à présent:
public static string TwoParameters()
{
Console.Write("Write some characters (i.e. 'cccaabbb'): ");
string myString = Console.ReadLine();
return myString;
Console.Write("Write a number - ");
int max = Convert.ToInt32(Console.Read());
}
public static void Counter(string myString, int max)
{
string myString = TwoParameters(myString);
foreach (char a in myString)
{
var occurences = myString.Count(x => x == 'a');
if (occurences > max)
max = occurences;
}
}
Erreurs que j'obtiens lors de l'exécution:
CS0136: Le local ou le paramètre 'myString' ne peut pas être déclaré dans la portée en raison de la portée locale englobante.
CS1501: Aucune surcharge pour la méthode 'TwoParameters' prend 1 argument.
CS1061: 'string' ne contient pas de définition pour count.
CS0165: Utilisation de la variable locale non attribuée 'myString'.
CS7036: Il n'y a aucun argument donné qui correspond au paramètre formel requis 'myString' de 'Program.Counter (string, int)'
Toute sorte d'indications sur ce que je fais mal, des suggestions sur la façon dont je peux améliorer mon code et / ou le terminer pour que le programme fasse la sortie seront extrêmement appréciées.
3 Réponses :
Une chaîne peut être traitée comme un IEnumerable. Vous pouvez utiliser LINQ pour d'abord grouper les caractères, puis n'en prendre que 2 dans chaque groupe, par exemple:
aabbc
Cela produit
var input="aaabbbbc";
var max=2;
var chars=input.GroupBy(c=>c)
.SelectMany(g=>g.Take(2))
.ToArray();
var result=new String(chars);
Cette requête regroupe les caractères avec GroupBy puis ne prend que max de chaque groupe avec Take . SelectMany aplatit tous les IEnumerable renvoyés par Take en un seul IEnumerable qui peut être utilisé pour créer une chaîne
Efkaresto! C'était vraiment utile.
Cette fonction respecterait également l'ordre dans la chaîne, donc aabcabc, 2 aboutirait à aabcbc:
public class Accumulator
{
public Dictionary<char, int> Histogram { get; } = new Dictionary<char, int>();
public StringBuilder Result { get; } = new StringBuilder();
}
Mais vous besoin aussi de cette petite classe d'aide:
static string ReturnMaxOccurences(string source, int count)
{
return source.Aggregate(new Accumulator(), (acc, c) =>
{
acc.Histogram.TryGetValue(c, out int charCount);
if (charCount < count)
acc.Result.Append(c);
acc.Histogram[c] = ++charCount;
return acc;
}, acc => acc.Result.ToString());
}
Cette méthode itère toute la chaîne et enregistre dans un histogramme les occurrences de chaque caractère. Si la valeur est inférieure à la valeur maximale souhaitée, elle sera ajoutée à la chaîne de résultat, sinon elle parcourt simplement le caractère et continue avec le suivant.
Super merci! En fait, je ne pense pas avoir précisé cela dans ma question, mais j'en avais certainement besoin pour respecter l'ordre. Vous avez été très utile!
Pointeurs sur ce que vous faites de mal:
TwoParameters a un code inaccessible Utiliser Linq est probablement un peu exagéré pour votre niveau de connaissance. Ceci est une version plus simple de la réponse de Oliver - en respectant également l’ordre des lettres:
abbaccd
Merci beaucoup! Une version simple devrait certainement bien correspondre à mon niveau de connaissances.
Eh bien, vous avez 5 erreurs ici - je vous suggère de vous concentrer sur une à la fois. Regardons d'abord la première erreur ... comprenez-vous ce que cela veut dire? Vous avez un paramètre appelé
myStringet vous essayez de déclarer une autre variable locale appeléemyString. Vous ne pouvez pas faire ça. Peut-être souhaitez-vous simplement attribuer une nouvelle valeur au paramètre à la place?diviser et conquérir: créez un StringBuilder vide. Répétez votre saisie par caractère et comptez jusqu'à max. Ajoutez le caractère actuel à Stringbuilder si consécutives , pas l’occurrence globale des lettres. Vous pouvez stocker votre nombre de lettres dans un dictionnaire si vous avez besoin d'un compte global.
est le nombre maximum d'un caractère limité à une séquence ou limite-t-il son occurrence sur toute la chaîne (comme dans
abcabcabc 2résultant enabcabcouabcabcabc code>)?@MikeLimaSierra L'entier est censé définir l'occurrence sur toute la chaîne. Votre exemple aboutira à «abcabc».