Étant donné une chaîne, je souhaite échanger 2 caractères dans la chaîne en fonction de leurs indices.
Entrée: str = "Bonjour" index1 = 1 index2 = 4
Sortie: str = "Holle"
mais quand j'essaye directement de mettre à jour le caractère de chaîne:
static string SwapChars(String str, int index1, int index2) { char[] strChar = str.ToCharArray(); char temp = strChar[index1]; strChar[index1] = strChar[index2]; strChar[index2] = temp; return new String(strChar); }
cela donne l'erreur ->
La propriété ou l'indexeur 'string.this [int]' ne peut pas être affecté à - c'est lecture seule
J'ai donc écrit une fonction qui convertit la chaîne en tableau de caractères avant d'effectuer l'opération d'échange.
str[1] = //Assign something
Cela fonctionne bien, mais je veux savoir quelle est la complexité temporelle de la fonction. Je pense que c'est O (n) car le tableau de caractères et la chaîne sont construits comme neufs, où n est la longueur de la chaîne passée. Existe-t-il également une autre façon d'effectuer cette opération avec de meilleures performances.
4 Réponses :
selon ce lien , une façon de remplacer des caractères dans une chaîne consiste à utiliser la classe StringBuilder
en c #,
var str = new String('a' , 100000000); var stopwatch = new Stopwatch(); stopwatch.Start(); var strBuilder = new StringBuilder(str); strBuilder[4] = 'e'; str = strBuilder.ToString(); stopwatch.Stop(); Console.WriteLine("Elapsed time using StringBuilder: {0} ms", stopwatch.Elapsed.Milliseconds); stopwatch.Reset(); stopwatch.Start(); char[] strChar = str.ToCharArray(); char temp = strChar[1]; strChar[1] = strChar[4]; strChar[4] = temp; stopwatch.Stop(); Console.WriteLine("Elapsed time using ToCharArray: {0} ms", stopwatch.Elapsed.Milliseconds); /* results: Elapsed time using StringBuilder: 179 ms Elapsed time using ToCharArray: 94 ms */
dans ce lien comparez la fonction c # String
et StringBuilder
, si vous voulez, vous pouvez comparer ces deux fonctions.
MODIFIER NOTE:
J'ai testé les deux méthodes StringBuilder et ToCharArray, les résultats montrent qu'utiliser ToCharArray et remplacer le char est vraiment mieux que d'utiliser la fonction StringBuilder, voici mon code testé (au moins dans ma machine):
var str = "Hello"; var strBuilder = new StringBuilder(str); strBuilder[4] = 'e'; str = strBuilder.ToString(); // the result will be same
Je pense que la complexité / performance du temps dans la solution ci-dessus sera la même que celle de la conversion en tableau de caractères.
La chaîne ne peut pas attribuer de valeur via l'indexeur car elle n'est pas autorisée à le faire. Lorsque vous recherchez la définition de string
, recherchez pour cet [index int]
vous saurez qu'il n'autorise que get
La meilleure façon de les échanger est basée sur votre méthode, mais n'a pas de valeur temporaire.
static string SwapChars(String str, int index1, int index2) { return str.Remove(index1, 1).Insert(index1, str[index2].ToString()) .Remove(index2, 1).Insert(index2, str[index1].ToString()); }
Une autre option consiste à utiliser Insert
et Remove
static string SwapChars(String str, int index1, int index2) { char[] strChar = str.ToCharArray(); strChar[index1] = str[index2]; strChar[index2] = str[index1]; return new String(strChar); }
Honnêtement, je préfère le premier car il est clair. P >
Votre méthode avec CharArray semble être la plus claire, merci
Vous pouvez utiliser des pointeurs, avec des allocations minimales
public static unsafe string SwapChars(string str, int index1, int index2) { if (str == null) throw new ArgumentNullException(nameof(str)); if (index1 < 0 || index1 >= str.Length) throw new ArgumentOutOfRangeException(nameof(index1)); if (index2 < 0 || index2 >= str.Length) throw new ArgumentOutOfRangeException(nameof(index1)); var result = new string(str); fixed (char* p = result) { var temp = p[index1]; p[index1] = p[index2]; p[index2] = temp; } return result; }
Notez que ce qui précède est assez dangereux, car cela va gâcher les chaînes non retournées
Ce serait plus sûr p>
public unsafe void SwapChars(ref string str, int index1, int index2) { fixed (char* p = str) { var temp = p[index1]; p[index1] = p[index2]; p[index2] = temp; } }
Je suis sûr que cela aura une complexité temporelle constante. Je veux juste savoir que nous utilisons des pointeurs s'il y a des précautions spéciales ou un comportement indéfini que je dois prendre en compte. Le code que vous avez écrit semble cependant assez simple.
@Jasmeet vous voudriez vérifier les index par rapport à la longueur, sinon vous pourriez obtenir une exception de mémoire. c'est à dire. faites juste une validation d'entrée au préalable
La sortie de ce `string test =" abcde "; SwapChars (test de référence, 1, 4); Console.WriteLine (test); test = "abcde"; Console.WriteLine (test); `n'est pas attendu, c'est ( aecdb aecdb
)
var result = new string (str);
dit: ne peut pas convertir de 'string' en 'char *'
, résoudre celui-ci devrait faire var result = new string (str.ToCharArray ());
mais cela irait à l'encontre de l'objectif d'avoir 'de meilleures performances' .... 😉
Je n'ai pas le temps de continuer avec cette réponse, s'il y a un problème, n'hésitez pas à copier le correctif et à coller votre propre réponse. J'aurai un autre regard dans la matinée
Je veux savoir quelle est la complexité temporelle de la fonction
Si n
"copie un caractère d'un emplacement mémoire à un autre", alors c'est O (2n + 3)
Vos caractères de chaîne sont copiés dans un tableau de caractères, vous les échangez, les caractères sont copiés dans une autre chaîne
Conservez votre chaîne en tant que tableau de caractères si vous souhaitez la muter
@CaiusJard Je reçois mon entrée sous forme de chaîne. Je ne peux pas changer ça.
Existe-t-il également un autre moyen d'effectuer cette opération avec de meilleures performances. - Conservez votre chaîne en tant que tableau de caractères si vous souhaitez la muter plus d'une fois