Utilisation de System.Move () Pour insérer / Supprimer l'élément (s) d'un tableau de chaîne n'est pas aussi simple que l'insertion / la supprime à partir d'un autre tableau de types de données simples. Le problème est ... la chaîne est une référence comptée dans Delphi. Utilisation de Move () sur les types de données comptés par référence nécessitent des connaissances plus approfondies sur le comportement du compilateur interne. P>
Quelqu'un peut-il ici expliquer les étapes nécessaires pour que je puisse réaliser cela, ou mieux avec des codes d'extraits, ou dirigez-moi à une bonne référence sur Internet? P>
Oh, s'il vous plaît, ne me dis-je pas d'utiliser la "façon paresseuse mais lente", c'est-à-dire pour la boucle, je sais que. P>
7 Réponses :
Pour insérer une chaîne, ajoutez simplement une chaîne (la méthode paresseuse) à la fin de la matrice (qui est une matrice de pointeurs), puis utilisez déplacer code> pour modifier l'ordre des éléments. de ce tableau (de pointeurs). p>
Si je voulais insérer une corde au milieu d'une liste des chaînes, j'utiliserais Tstringlist.insert. (Il utilise-t-il rapidement System.Move.) P>
Une raison particulière pour laquelle vous utilisez un tableau au lieu d'une TStringList? P>
Pour la raison de la performance, car mon tableau serait possible d'être rempli d'énormes objets. Je réalise que Tstringlist.Capacité aidera, mais Tstringlist fera toujours une vérification inutile - selon la documentation-- "... Affectation d'une valeur plus petite que le comptage supprime les chaînes de la fin de la liste. Affectation d'une valeur supérieure à celle des comptes. espace pour plus de strings à ajouter. " Dans mon cas, je n'ai pas besoin d'un tel chèque.
@Phantom: Eh bien, tant que vous mesurez la surcharge réelle de l'approche code> TStringlist code>. De nombreuses personnes sont étonnamment tolérantes à des retards de quelques millisecondes.
@Phantom: assez juste, mais il y a d'autres implications de performance à prendre en compte. Par exemple, si vous devez remplir votre matrice avec un grand nombre de chaînes, utilisez-vous setlength (myarray, longueur (myarray) + 1) code> à chaque fois? C'est un grand nombre de réallocs et de copies, et cela peut vraiment faire glisser la performance. Pour écarter cette question, vous devez allouer plus d'espace que vous utilisez, vous avez donc besoin de quelque chose pour garder une trace de la capacité et du nombre actuel. Pour gérer cela, vous devez l'encapsuler dans un objet ... et ensuite vous êtes bien sur la route pour réinventer la TStringList. : P
Oui, Mason est absolument juste. L'exemple de son commentaire est l'un des problèmes de performance Delphes les plus courants et les plus graves. Mais, @Phantom, puisque vous parlez de déplacer code>, je suppose que vous êtes déjà au courant de ce problème.
@ Mason, non, je vais allouer une mémoire, il suffit de dire pour 16384 articles et allouera plus de 16384 s'il est apparemment nécessaire.
@ Mason, je n'ai pas l'intention de réinventer Tstringlist. Il y a tellement de fonctionnalités dans Tstringlist que je n'ai pas besoin de travailler dans ce tableau. Pour être honnête, le tableau sera doté de tous les fichiers de tous les disques durs attachés à un ordinateur.
@Phantom: Mais vous avez besoin de réorganiser les éléments du tableau?
@Andreas, non, les articles n'ont pas besoin d'être triés.
AFAIK, car les éléments de suppression ou d'insertion à une matrice ne nécessitent aucun mécanisme de tri / d'indexation.
@Andreas, TStringList Utilisez System.Move () au lieu d'une telle boucle. En ce qui concerne la mise en œuvre de TstringList en un coup d'œil, je ne pouvais pas saisir les conditions réelles pour utiliser le déplacement () sur les types de données comptés de référence. Cependant, il semble que je dois l'étudier plus profondément, ainsi que le commentaire de @ Patrickvl.
@Phantom: TStringList CODE> (bien sûr!) Utilise uniquement
Déplacer code> si cela doit modifier l'ordre des chaînes, par exemple, si vous insérez une chaîne au milieu de la Array (pour ensuite toutes les chaînes après la nouvelle insérée, il est nécessaire de descendre dans la matrice). Si vous ajoutez simplement une chaîne au bas de la matrice, aucun
Déplacer code> n'est nécessaire, ni dans un tableau
de chaîne code> ni dans un
TStringList code>!
@Andreas, Oups, j'ai mal compris ce que vous vouliez dire, maintenant je l'attrape. :-)
Si vous utilisez System.Move pour mettre des éléments dans une gamme de chaînes, vous devez savoir que les chaînes qui, avant le déménagement (et maintenant écrasées), avaient un nombre de référence de -1 pour des chaînes constantes, ou > 0 pour les chaînes variables. Les chaînes constantes ne doivent pas être modifiées, mais les chaînes variables doivent être traitées en conséquence: vous devez réduire manuellement leur nombre de référence (avant qu'ils ne soient écrasés!). Pour ce faire, vous devriez essayer quelque chose comme ceci:
Dec(PStrRec(IntPtr(SomeString)-12).refCnt);
@Patrickvl: Donc, vous me recommandez toujours d'utiliser TStringList même si pour mon cas, c'est-à-dire que la matrice sera remplie de tous les fichiers de tous les disques durs attachés à un ordinateur. Tstringlist sera-t-il assez rapide?
@Phantom: Tstringlist a été conçu pour manipuler un grand nombre de cordes. Si vous avez Delphi, vous avez des cours.Pas; Parcourez le code à Tstringlist et Tstrings et voyez le nombre de bits de code que vous pouvez trouver qui existe spécifiquement pour des raisons de performance. C'est l'une des classes les plus utilisées de l'ensemble du RTL, et il a été essentiellement testé pendant 15 ans maintenant. Vous devriez travailler assez fort pour proposer une solution sensiblement plus rapide que TStringList lors de la manipulation des cordes. Si vous voulez savoir si c'est lent, essayez de l'utiliser et voyez si cela se sent lent ou non.
-1 Pour suggérer une modification manuelle des structures de données internes définies par la mise en œuvre. Vous auriez pu simplement affecter sulsing: = '' code> et que le compilateur s'occupe de la situation de dénonciation zéro-référence, ainsi que de la sécurité thread-sécurité.
@ROB: Je répondais simplement à la question de Phantom comment réduire le nombre de références manuellement. Je crois que c'est une question valable de répondre - même quand il n'est pas conseillé de le faire! (Est-ce que je n'ai pas mentionné cela dans ma dernière déclaration?) Sûr, régler suls: = '' code> fonctionne aussi, mais qui repose sur la magie du compilateur, alors ma réponse a une crédibilité, n'est-ce pas pense?
Non, Patrick, la question de pas i> demande comment réduire le nombre de références d'une chaîne. Phantom a simplement indiqué qu'il savait que le comptage de référence était un problème qui se préoccupe lors de l'utilisation de Move, il a donc demandé comment utiliser le déplacement pour ajuster un éventail de chaînes. Il n'y avait rien à suggérer que la matrice était en réalité une blob de mémoire non typée, il n'y a donc aucune raison de penser que le compilateur Magic n'est pas disponible.
appelez unique () dessus, avant de jouer avec elle. P>
http://docwiki.embarcadero.com/vcl/en/system.uniqueString p>
Ensuite, vous avez une chaîne avec une seule référence. P>
Fat Chance que c'est ce que le fait de supprimer et d'insérer aussi, et je doute que vous soyez plus rapide. P>
"Fat Chance" signifie que quelque chose est improbable i>. Par exemple: "Pensez-vous que notre patron va nous donner un bonus cette année?" "Graisse de chance!" Appeler uniquesString est exactement i> quelle suppression et l'insertion fera pour changer le contenu du caractère d'une chaîne. Il n'est pas nécessaire de l'appeler lors de la modification du contenu de l'élément d'une matrice dynamique, cependant.
Oups, les expressions sont toujours douloureuses dans les langues étrangères :-) Quoi qu'il en soit, j'ai raté le "tableau de" bit. Ensuite, finalisez simplement les bits supprimés et initialiser les bits non supprimés (ou les remplir avec zéro) feraient
J'ai démontré comment supprimer des articles d'un tableau dynamique avant:
Dans cet article, je commence par le code suivant: p> vous ne peut pas vous tromper em> avec ce code. Utilisez quelle valeur pour depuis pour l'insertion, vous venez de déplacer des choses la direction opposée: p> Utiliser x code> vous voulez; Dans votre cas, remplacez-le par
chaîne code>. Si vous souhaitez obtenir plus d'amateur et utiliser
déplacer code>, il y a le chemin à faire cela aussi. P>
x code> x est
string code>, l'appel de
finaliser code> équivaut à l'attribution de la chaîne vide à cet élément de tableau. J'utilise
finaliser code> dans ce code, car il fonctionnera pour tous les types d'éléments de tableau em>, même des types qui incluent des enregistrements, des interfaces, des chaînes et d'autres tableaux. p>
finaliser code> quand vous serez sur le point de faire quelque chose qui est à l'extérieur Les limites de la langue, telles que l'utilisation de la procédure CODE> MODER CODE> NON-SAFE pour écraser une variable d'un type géré par le compilateur. Utilisez
initialiser code> lorsque vous rentrez dans la partie définie de la langue. (La langue définit ce qui se passe lorsqu'un tableau se développe ou rétrécit avec
setlength code>, mais il ne définit pas comment copier ou supprimer des chaînes sans utiliser une déclaration d'affectation de chaîne.) P> P> P> P> P> P> P> P> >
Merci beaucoup. :-) Je vais essayer votre code d'extraction et accepterai cela comme réponse acceptée si cela réussit. Mais je dois aller au bureau maintenant. :-)
Juste une suggestion, ou peut-être une demande, nous serons heureux si vous souhaitez mettre à jour votre article mentionné pour inclure également l'insertion. J'aime votre conception de page Web.
J'ai modifié le code de Rob pour fournir une façon de le faire en utilisant la construction de Tarray plus récente
Devrait être: Termings: = Althength - Index - 1; dans deletex ()
Voulant simplement ajouter ceci pour des personnes qui viennent ici à l'avenir.
Modification du code de Rob, j'ai proposé cette façon de le faire qui utilise le nouveau une chose similaire peut être fait pour l'insert. p> (ne cherche pas que cela soit marqué comme la réponse, je cherche juste à fournir Un exemple qui était trop long pour s'adapter aux commentaires sur l'excellente réponse de Rob.) p> (fixé aux commentaires de Rob ci-dessous.) p> p> TARRAY
Vous avez tenté de faire trop de changements à la fois. Faire de mon code Utiliser Generic TARRAY CODE> aurait été bien, mais vous avez décidé d'ajouter une autre fonctionnalité et de le faire, vous avez enfreint le tout. Je ne pense pas qu'il y ait une entrée i> qui rend cette fonction fonctionne.
Avez-vous quelque chose de plus spécifique à dire que cela? En fait, j'ai réparé l'erreur que je crois est là (j'avais mon 0/1 transposé sur le si index = 0 puis code> conditionnel). Je l'utilise actuellement en ce moment et ça marche apparemment bien. S'il y a une erreur, il n'est certainement pas très évident au débogage / runtime. Critique constructive accueillie.
Pouvez-vous expliquer comment cela répond à la question "Utilisation de MOVE () pour insérer / supprimer des éléments d'un tableau dynamique de chaîne"? Je vois une boucle itérative qui n'a rien à voir avec l'utilisation de code> Whatsover, ne s'adresse pas à un tableau dynamique de la chaîne code> (A TARRAY générique
La transposition n'a pas aidé. Tout temps index code> est non nul, vous finissez par écrire sur
A [-1] code>. Le premier endroit que vous écrivez doit toujours être
un [index] code>. Regardez mon code. Pourquoi l'index de départ est-il toujours conditionnel? Vous pouvez vous rapprocher de votre fonctionnalité souhaitée en revenant à mon code et en remplaçant chaque occurrence de
1 code> avec
compte code>.
Merci, c'était plus constructif. En fait, il cherchait principalement mon code après une nuit de sommeil et allait "attendre, pourquoi ai-je écrit ça?" Je n'ai aucune idée à ce stade, mais la réponse était assez évidente. J'ai traversé plusieurs tours de stylo et de quadroughs de papier, alors je suis convaincu que c'est juste à ce stade.
Vous n'êtes pas indiquant s'il est important que vous gardes les éléments de la matrice dans le même ordre ou non.
Si la commande n'est pas pertinente, vous pouvez alors quelque chose trier la liste forte> trier la liste automatiquement forte>
Si vous avez une énorme liste qui doit être modifiée par l'utilisateur, vous pouvez utiliser des méthodes similaires à celle ci-dessus (casser la commande de liste). Lorsque l'utilisateur a fait son édition (après plusieurs suppressions), vous le présentez avec un bouton appelé "liste de tri". Maintenant, il peut faire l'opération longue (tri).
Bien sûr, je suppose ci-dessus que votre liste peut être triée par un certain paramètre. P>
Une alternative consiste à automatiser le processus de tri. Lorsque l'utilisateur a supprimé des choses de la liste, démarrez une minuterie. Continuez à réinitialiser la minuterie si l'utilisateur conserve des éléments. Lorsque la minuterie parvient à déclencher un événement, faites le tri, arrêtez la minuterie. P> p>