1
votes

Utilisation de deux paramètres (string, int) pour définir un nombre maximum de caractères spécifiques dans la sortie de chaîne

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.


4 commentaires

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é myString et vous essayez de déclarer une autre variable locale appelée myString . 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 2 résultant en abcabc ou abcabcabc )?


@MikeLimaSierra L'entier est censé définir l'occurrence sur toute la chaîne. Votre exemple aboutira à «abcabc».


3 Réponses :


3
votes

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


1 commentaires

Efkaresto! C'était vraiment utile.



1
votes

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.


1 commentaires

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!



0
votes

Pointeurs sur ce que vous faites de mal:

  • vous réinitialisez votre maximum donné aux nombres de votre chaîne
  • vous ne gérez que "a"
  • votre fonction TwoParameters a un code inaccessible
  • vous essayez de déclarer à nouveau un nom de variable en le fournissant déjà à la fonction en tant que paramètre
  • vous ne créez pas de chaîne à afficher

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


1 commentaires

Merci beaucoup! Une version simple devrait certainement bien correspondre à mon niveau de connaissances.