4
votes

Comment tout déplacer vers le haut d'un endroit dans un tableau? C #

J'essaie de créer une méthode qui déplace chaque caractère entre le premier et le dernier caractère d'un tableau vers le haut. De plus, le premier au dernier caractère doit «se déplacer» vers le deuxième endroit du tableau ([1]). en bref, je veux que «abcdef» devienne «aebcdf». Voici ce que j'ai trouvé:

                if (myArray.Length > 3)
            {
                char savechar = myArray[myArray.Length - 2];
                for (int t = 1; t < (myArray.Length - 2); t++)
                {
                    myArray[t++] = myArray[t];
                }
                myArray[1] = savechar;
            }

Le problème ici est que cela déplace simplement le deuxième personnage vers la fin, au lieu de déplacer tous les personnages d'un endroit. (Je sais pourquoi ça fait ça, je ne sais juste pas comment je peux résoudre ça) Quelqu'un aide?


9 commentaires

êtes-vous obligé d'utiliser le changement de caractère avec la boucle for? ou pouvez-vous utiliser la requête LINQ?


On dirait que vous devez échanger les deux caractères, pas simplement attribuer


Si possible, j'aimerais utiliser une boucle for, oui. Je viens de commencer à programmer, je n'ai pas encore entendu parler de LINQ ...


Ce que vous allez vouloir faire, c'est atteindre l'intérieur du tableau, extraire "le premier au dernier caractère" (qui semble être "l'avant-dernier"), le mettre dans une variable pour plus tard. Puis boucle, de l'arrière vers l'avant, (en sautant le dernier caractère et le premier caractère) et en copiant le caractère (n-1) dans le point (n). Lorsque vous avez terminé, placez l'avant-dernier personnage que vous avez mis de côté à la deuxième place. N'oubliez pas que tout est basé sur 0 (ce qui fonctionne très bien en boucle de 0 à n-1, mais c'est très bizarre dans l'autre sens.


Stockez l'avant-dernier élément (élément n-1; e ) dans une variable temporaire. Utilisez un seul appel de Array.Copy pour déplacer les éléments 1, ..., n-2. Placez l'élément dans la variable temp dans l'emplacement de tableau n ° 1. Terminé...


Je recommande aux programmeurs débutants de résoudre d'abord ce problème sur papier; en fait, prenez un morceau de papier, un crayon et une gomme, écrivez le tableau sur la page, puis simulez les opérations que vous devez effectuer. Notez soigneusement chaque petite étape que vous faites en cours de route , puis traduisez soigneusement cet algorithme en code.


Aussi: rompez-vous avec l'habitude d'utiliser ++ dans une autre expression dès maintenant . Cela ne fait rien pour vous, si ce n'est de rendre votre algorithme plus difficile à comprendre et à obtenir correctement.


Merci pour les conseils @EricLippert :)


La variable doit-elle être un tableau? Si vous prévoyez de déplacer des éléments de cette manière, vous feriez peut-être mieux d'utiliser une List qui déplacera les autres éléments lorsque vous add ou supprimer . Ou utilisez une liste temporaire et reconvertissez-le en un tableau une fois que vous avez terminé de déplacer des éléments.


7 Réponses :


2
votes
  1. Commencez par la fin plutôt que par le début afin de ne pas copier les caractères que vous avez déjà modifiés.
  2. Je ne pense pas que vous ayez l'intention d'utiliser "++" dans votre boucle. Cela modifie la valeur de t et n'est pas nécessaire.
  3. Voici le code résultant:

    if (myArray.Length > 3)
    {
        char savechar = myArray[myArray.Length - 2];
        for (int t = myArray.Length - 2; t > 1; t--)
        {
            myArray[t] = myArray[t-1];
        }
        myArray[1] = savechar;
    }
    

3 commentaires

@meilelhorst: C'est exactement ce que j'ai décrit dans mon commentaire. Voyez si vous pouvez comprendre comment faire cela à partir du commentaire sans regarder ce code.


@ Flydog57 Merci à tous les deux! Je me demandais si le fait de passer de l'arrière à l'avant ferait une différence, et je suis heureux de le voir. J'essaierai de réécrire le code plusieurs fois moi-même pour mieux le comprendre;)


@MielElhorst: Si vous suivez les conseils d'Eric Lippert (pour le faire d'abord sur papier), vous verrez que la façon de faire ce travail (sur papier) est de commencer par la fin et de travailler à rebours. Si vous commencez par le début, vous n'avez pas de "cases vides" pour placer votre personnage nouvellement déplacé, alors que si vous commencez à la fin, vous pouvez le déplacer vers l'emplacement le plus récemment libéré.



2
votes

Cela donne le résultat souhaité. Notez qu'il n'y a pas de vérification de longueur puisque j'utilise votre entrée d'échantillon. Et aucun effort pour le rendre efficace;)

var list = "abcdef".ToCharArray().ToList();    
var item = list.ElementAt(list.Count - 2);
list.RemoveAt(list.Count - 2);
list.Insert(1, item);
var reordered = string.Join(string.Empty, list);


0 commentaires

1
votes

Voici ma prise:

for (int i = 1; i < input.Length - 1; i++)
{
  var temp = input[i];
  input[i] = input[input.Length - 2];
  input[input.Length - 2] = temp;
}


0 commentaires

0
votes

cela ne fonctionnera que pour les chaînes, mais cela fonctionne:

    var text = "abcdef";
    var shifted = text.First() + text.Substring(text.Length - 2, 1) + text.Substring(0, text.Length - 2) + text.Last();


0 commentaires

0
votes

Voici un algorithme universel pour faire défiler le tableau de décalage par les éléments shiftCount et ignorer les skippedElements au début et à la fin de array :

var array = new char[] {'a', 'b', 'c', 'd', 'e', 'f'};

var skippedElements = 1;
var shiftCount = 1;
bool shiftLeft = true;
if (shiftLeft)
{
    // shift left
    Array.Reverse(array, skippedElements, shiftCount);
    Array.Reverse(array, skippedElements + shiftCount, array.Length - skippedElements * 2 - shiftCount);
    Array.Reverse(array, skippedElements, array.Length - skippedElements - shiftCount);

}
else
{
    // shift right
    Array.Reverse(array, skippedElements, array.Length - skippedElements * 2);
    Array.Reverse(array, skippedElements + shiftCount,  array.Length - skippedElements * 2 - shiftCount);
    Array.Reverse(array, skippedElements, shiftCount);
}

C'est une modification pour Algorithme d'inversion pour la rotation du tableau . Cela fonctionne pour skippedElements> 0 . il ne nécessite pas de variables ou de mémoire supplémentaires.


0 commentaires

1
votes

Utilisation de Array.Copy:

if (myArray.Length > 3)
{
    char savechar = myArray[myArray.Length - 2];
    Array.Copy(myArray, 1, myArray, 2, myArray.Length - 3);
    myArray[1] = savechar;
}


0 commentaires

0
votes

Pour ce que ça vaut, j'opterais probablement pour la solution Array.Copy de NPCampbell s'il s'agissait d'un système de production, mais pour des raisons de démonstration (et juste un peu de plaisir au code-golf), voici une solution utilisant Linq:

var n = myArray.Length - 1;
var newArray = myArray.Select((_, i) => myArray[i % n > 0 ? (i > 1 ? i : n) - 1 : i]).ToArray();

Ce n'est pas l'option la plus performante et certainement pas la très lisible, mais ça marche.


0 commentaires