Suite

Vous obtenez des résultats erronés dans le curseur de recherche du script ArcPy/Python ?


J'ai deux fonctions :

  1. Le premier créera la couche d'entités
  2. le second accédera au même calque créé et imprimera le résultat.

lorsque j'exécute mon script pour la première fois, il imprimera les mauvais résultats. quand je le lance la deuxième fois, il imprime le résultat correct…

Script de résultat incorrect exécuté pour la première fois :

accéder à la couche de carte 2

(répété plusieurs fois)

.

Résultat correct : exécuter le script une deuxième fois 1. le calque qui est en train de créer ne contient que 5 lignes, donc mon script n'imprime que 5 messages

accéder à la couche de carte 1

répété pour toutes les couches.

Scénario:

# import system modules import arcpy import math import sys import traceback from arcpy import env # Class to Build Boundry of Districts class Build_Boundry: def __init__(self, workSpace,mapLayerFinal,censusLayer,totalDistricts,mxdLocation): self.workSpace = workSpace self.censusLayer = recensementLayer self.mapLayerFinal = mapLayerFinal self.totalDistricts = totalDistricts self.mxdLocation = mxdLocation # Fonction pour calculer la moyenne du nombre total d'électeurs dans chaque district def boundry(self): arcpy.AddMessage("Building Boundry of Districts ") if arcpy.Exists( self.mapLayerFinal): arcpy.AddMessage("La couche existe déjà… ") print(self.mapLayerFinal) else: arcpy.MakeFeatureLayer_management(self.censusLayer, self.mapLayerFinal,"DISTRICT_ID BETWEEN 1 AND "+str(self.totalDistricts), self.workSpace) # Exécutez la fusion en utilisant LANDUSE et TAXCODE comme champs de fusion arcpy.Dissolve_management(self.mapLayerFinal, str(self.workSpace)+"/"+str(self.mapLayerFinal), "DISTRICT_ID", "","MULTI_PART" , "DISSOLVE_LINES") p rint(self.mapLayerFinal) arcpy.AddMessage("Limite des districts calculée") mxd = arcpy.mapping.MapDocument(self.mxdLocation) df = arcpy.mapping.ListDataFrames(mxd, "")[0] addLayer = arcpy.mapping .Layer(self.mapLayerFinal) arcpy.mapping.AddLayer(df, addLayer,"BOTTOM") mxd.save() arcpy.RefreshTOC() del mxd, addLayer return ; # Classe pour calculer la compacité class Calculate_Compactness: def __init__(self, workSpace,mapLayerFinal): self.workSpace = workSpace self.mapLayerFinal = mapLayerFinal # Fonction pour calculer la compacité def compactness_quotient(self): arcpy.AddMessage("Calcul du quotient de compacité") avec arcpy.da.SearchCursor(self.mapLayerFinal,["Shape_Area","DISTRICT_ID","Shape_Length"]) en lignes : print "layer "+str(self.mapLayerFinal) pour la ligne dans les lignes : area = row[0] district_id = row[1] périmètre = row[2] print "obtenir l'accès à la couche de carte "+str(district_id) print "Calcul du processus de quotient de compacité terminé" return ; dossier = "C:/Users/Abrar ahmad/Desktop/CASES/Rural/Case_1_Boundary_Input" mxdLocation = r"C:/Users/Abrar ahmad/Desktop/CASES/Rural/Case_1_Boundary_Input/New_Rwp_Cencus = "Cencus.mxd" workSpace.mxd:/ /Abrar ahmad/Desktop/CASES/Rural/Case_1_Boundary_Input/Selected_BU2.gdb" env.workspace = workSpace recensementLayer = "Rural_Area_Rwp" districtsLayer = "Existing_District_Boundary" totalDistricts = int(5) mapLayer_Final = str #(districts toLayer) Build Boundry boundry = Build_Boundry(workSpace,mapLayerFinal,censusLayer,totalDistricts,mxdLocation) boundry.boundry() cc = Calculate_Compactness(workSpace,mapLayerFinal) cc.compactness_quotient()

Il y a une variable qui entre en collision dans MakeFeatureLayer et Dissolve_Management. l'a changé en couche_temp

arcpy.MakeFeatureLayer_management(self.censusLayer, "tmp_Layer","DISTRICT_ID BETWEEN 1 AND "+str(self.totalDistricts),self.workSpace) # Exécuter la fusion en utilisant LANDUSE et TAXCODE comme champs de fusion arcpy.Dissolve_management("tmp_Layer", str( self.workSpace)+"/"+str(self.mapLayerFinal), "DISTRICT_ID", "","MULTI_PART", "DISSOLVE_LINES")

Coordonnées globales et calculez la distance.

Premièrement, les coordonnées du maillage sont locales et l'emplacement du curseur de la scène est global. Soit convertir le curseur de la scène en local

puis le résultat revient à global lors de l'ajout du vide.

Cela ne nécessiterait que 2 multiplications matricielles.

ou convertissez les coordonnées du maillage en globales (vous l'avez fait ci-dessous)

puisque nous n'écrivons pas au bmesh, il ne sera donc pas reflété de manière permanente.

Quel point le plus proche sur la ligne fait.

Il trouve renvoie le point sur la ligne la plus proche du point, et quel pourcentage c'est à partir du point de départ, c'est à dire 0 est le point de départ, 1 l'autre extrémité. Il ne sort pas de la ligne.

Dans l'exemple ci-dessus, remarquez que les deux ont le même résultat, alors que l'un est juste au milieu de la ligne, l'autre ne l'est pas. Également évident dans l'image de la question, le résultat est le plus petit rapport du coin aka bord vert 0. Le retournement des normales changera l'ordre des sommets déplacera à nouveau ce résultat, s'il est à 10% du coin (tel quel) sera à 90% avec les verts l'autre côté.

Au lieu de cela, calculez la distance en soustrayant le coup de l'emplacement du curseur.

Ont modifié le code pour ajouter vide au point de fermeture de tous les bords, plutôt que seulement celui de la face zéro.

Autres constructions pour min/max

Au lieu de définir une valeur très élevée comme max et de tester à chaque itération, il existe d'autres moyens de trouver un minimum et un maximum (numpy est extrêmement bon pour cela)

Une autre consiste à faire une liste de tous les résultats et à les trier. Le zéro sera le plus proche, le dernier le plus éloigné.


L'encodage ArcPy et Python ne fonctionne pas ?

Je suis confronté à un comportement étrange entre l'encodage ArcPy et Python. Je travaille avec VisualStudio 2010 Shell avec les outils Python pour VS (PTVS) installés. J'ai isolé mon problème via un simple fichier de script. Le fichier de script py qui contient les commandes suivantes. Dans VisualStudio, j'ai défini les « Options de sauvegarde avancées. » à « UTF-8 sans signature ». Le script imprime simplement à l'écran une chaîne accentuée, puis importe le module arcpy, puis imprime à nouveau la même chaîne. L'importation d'Arcpy semble changer la configuration de l'encodage Python mais je ne sais pas pourquoi et j'aimerais le rétablir correctement car cela pose des problèmes un peu partout dans le script d'origine.

J'ai vérifié le dossier « encoding » de python et j'ai effacé tous les fichiers pyc. Ensuite, j'ai exécuté le script et il a généré 3 fichiers pyc :

  1. cp850.pyc (qui correspond à mon stdout.encoding)
  2. cp1252.pyc (qui correspond à l'encodage de mon environnement Windows)
  3. utf_8.pyc (qui correspond à l'encodage de mon script)

Lors de l'importation d'ArcPy, quelque chose vient modifier l'encodage qui affecte les variables initiales.

Est-il possible avec une commande Python de trouver où se trouve le code ArcPy cp1252 et de le lire afin que je puisse créer une fonction qui le traite?

et quand je lance le script, j'obtiens ces résultats :

Encodage chargé : ascii
Définir l'encodage : utf-8

Type d'origine : tapez 'unicode'
Texte original : Récupération des données <--- C'est vrai

importer arcpy
Encodage chargé : utf-8

arcpy mess up type original : tapez 'unicode'
arcpy mess up texte original : R'cuperation des donn'es> <--- C'est faux
arcpy gâcher ReEncode avec cp1252 type : tapez 'str'
arcpy mess up ReEncode with cp1252 text : Récupération des données> < --- Cela correspond à l'unicode d'origine


Les membres de contexte disponibles dépendent de la zone de blender actuellement accessible.

De nombreux opérateurs disposent d'une fonction « sondage » qui peut vérifier que la souris est une zone valide ou que l'objet est dans le bon mode (mode édition, peinture au poids, etc.). Lorsqu'une fonction de sondage d'un opérateur échoue dans python, une exception est levée.

En savoir plus sur l'utilisation des opérateurs et pourquoi vous rencontrez des échecs d'interrogation (la souris n'est pas sur la zone de l'écran droit ou le mauvais mode / autre condition préalable). Voir également la section Gotchas de la documentation de l'API à ce sujet.

  1. Exécutez un opérateur via le menu de la barre d'espace (voir en bas de la section) dans Blender 2.7x ou en utilisant F3 à partir de Blender 2.8x à partir de la zone appropriée ( bl_options ne doit pas contenir 'INTERNAL' )
  2. Spécifiez le droit contexte d'exécution pour l'appel opérateur (cela corrige l'erreur de contexte seulement pour certains !)
    (docs API, exemple)
  3. Utiliser un remplacement pour transmettre les arguments de contexte requis
  4. Modifier temporairement le type de zone
  5. Utilisez des fonctions API "bas niveau" pour obtenir le même résultat sans soucis de contexte

Passer outre

Cela ne semble pas fonctionner pour cet opérateur ? ! Il ajoute un fond mais sans nom/texture.

D'ailleurs:
Vous pouvez passer un dict vide (comme bpy.ops.example.operator(<>) ), qui imprime généralement des avertissements à la console système concernant les membres de contexte manquants. Vous devez passer ces membres et répéter jusqu'à ce qu'il ne se plaigne plus. Mais méfiez-vous de certains opérateurs, qui nécessitent des bases de scènes - si vous ne leur fournissez pas de référence, Blender plantera sur le bureau avant même que vous ne découvriez qu'ils sont nécessaires.

Changer le.type de zone

Niveau faible

Semblable à la substitution, vous avez besoin d'une instance de vue 3D, dans ce cas ses données d'espace (car c'est l'endroit où résident les arrière-plans). Le code suivant prend la première vue 3D de la disposition d'écran actuelle (s'il y en a une), ajoute un nouvel arrière-plan et définit l'image sur un bloc de données d'image :


3 réponses 3

Je pense que ces réponses deviennent toutes a) beaucoup trop compliquées et b) hors de propos par rapport à ce que l'utilisateur 2023861 veut accomplir :

"J'essaie de déclarer une variable, puis de sélectionner cette variable." signifie deux choses différentes dans PL/SQL ou dans SQLplus, et peut-être deux autres choses dans DBArtisan. Pour atteindre l'objectif dans SQLplus, utilisez des "Variables de substitution". un excellent fond se trouve ici.

Mon exemple ne suit pas précisément votre exemple SQL Server T-SQL, mais il est proche et n'est PAS procédural (lire : pas de bloc PL/SQL anonyme.)

PL/SQL avec variables de substitution :

Le tout à l'invite SQL-Plus. de ma table d'employés fictifs, j'ai obtenu ce résultat :

Si vous souhaitez rendre cela semi-procédural, vous utilisez les variables BIND et la syntaxe déclarative de PL/SQL similaire à T-SQL. (À mon avis, il s'agit d'un ÉNORME gaspillage d'efforts, mais il est inclus pour aider à clarifier les types de variables.)

SQLPlus utilisant des variables de liaison PL/SQL :

Approche entièrement procédurale utilisant PL/SQL :

Alors, quand dois-je utiliser chaque cas ? J'utilise des variables de substitution SQLplus 75% du temps lorsque j'écris des scripts SQL dont je souhaite paramétrer l'entrée. L'exécution d'un script à l'invite SQLplus permet de passer des arguments entrants, donc mes variables de substitution préférées sont &1 et &2 comme dans l'exemple suivant :

et exécute un code SQL similaire à

Remarquez comment les arguments entrants sont affectés à des variables de substitution, puis utilisés dans l'instruction SQL. Je n'utilise jamais l'exemple du milieu, et j'utilise toujours les 3èmes exemples (PL/SQL procédural) lors de l'écriture de fonctions, procs et packages.


Vous obtenez des résultats erronés dans le curseur de recherche du script ArcPy/Python ? - Systèmes d'information géographique

Ceci est Python version 3.11.0 alpha 0

Copyright (c) 2001-2021 Python Software Foundation. Tous les droits sont réservés.

Voir la fin de ce fichier pour plus d'informations sur les droits d'auteur et la licence.

  • Site Web : https://www.python.org
  • Code source : https://github.com/python/cpython
  • Suivi des problèmes : https://bugs.python.org
  • Documentation : https://docs.python.org
  • Guide du développeur : https://devguide.python.org/

Pour des instructions plus complètes sur la contribution au développement de CPython, consultez le Guide du développeur.

Des kits Python installables et des informations sur l'utilisation de Python sont disponibles sur python.org.

Sous Unix, Linux, BSD, macOS et Cygwin :

Cela installera Python en tant que python3 .

Vous pouvez passer de nombreuses options au script de configuration run ./configure --help pour en savoir plus. Sur les systèmes de fichiers macOS insensibles à la casse et sur Cygwin, l'exécutable s'appelle python.exe ailleurs c'est juste python .

La création d'une installation Python complète nécessite l'utilisation de diverses bibliothèques tierces supplémentaires, en fonction de votre plate-forme de construction et des options de configuration. Tous les modules de bibliothèque standard ne sont pas constructibles ou utilisables sur toutes les plateformes. Reportez-vous à la section Installer les dépendances du Guide du développeur pour obtenir des informations détaillées à jour sur les dépendances pour diverses distributions Linux et macOS.

Sur macOS, il existe des options de configuration et de construction supplémentaires liées au framework macOS et aux versions universelles. Reportez-vous à Mac/README.rst.

Si vous le souhaitez, vous pouvez créer un sous-répertoire et appeler configure à partir de là. Par exemple:

(Cela échouera si vous également construit dans le répertoire de niveau supérieur. Vous devriez d'abord faire un nettoyage au niveau supérieur.)

Pour obtenir une version optimisée de Python, configurez --enable-optimizations avant d'exécuter make . Cela définit les cibles make par défaut pour activer l'optimisation guidée par profil (PGO) et peut être utilisé pour activer automatiquement l'optimisation du temps de liaison (LTO) sur certaines plates-formes. Pour plus de détails, consultez les sections ci-dessous.

PGO tire parti des versions récentes des compilateurs GCC ou Clang. S'il est utilisé, soit via configure --enable-optimizations, soit en exécutant manuellement make profile-opt indépendamment des indicateurs de configuration, le processus de génération optimisé effectuera les étapes suivantes :

L'intégralité du répertoire Python est nettoyée des fichiers temporaires pouvant résulter d'une compilation précédente.

Une version instrumentée de l'interpréteur est construite, en utilisant des indicateurs de compilateur appropriés pour chaque saveur. Notez qu'il ne s'agit que d'une étape intermédiaire. Le binaire résultant de cette étape n'est pas bon pour les charges de travail réelles car il contient des instructions de profilage intégrées.

Une fois l'interpréteur instrumenté construit, le Makefile exécutera une charge de travail d'entraînement. Ceci est nécessaire pour profiler l'exécution de l'interpréteur. Notez également que toute sortie, à la fois stdout et stderr, qui peut apparaître à cette étape est supprimée.

L'étape finale consiste à construire l'interpréteur réel, en utilisant les informations collectées à partir de celui instrumenté. Le résultat final sera un binaire Python optimisé pour une installation de distribution ou de production.

Activé via le drapeau --with-lto de configure. LTO tire parti de la capacité des chaînes d'outils de compilateur récentes à optimiser la limite de fichier .o par ailleurs arbitraire lors de la création d'exécutables finaux ou de bibliothèques partagées pour des gains de performances supplémentaires.

Nous avons un aperçu complet des changements dans le document What's New in Python 3.10. Pour un journal des modifications plus détaillé, lisez Misc/NEWS, mais un compte rendu complet des modifications ne peut être glané qu'à partir de l'historique des commits.

Si vous souhaitez installer plusieurs versions de Python, consultez la section ci-dessous intitulée « Installation de plusieurs versions ».

Il peut également être téléchargé dans de nombreux formats pour un accès plus rapide. La documentation est téléchargeable aux formats HTML, PDF et reStructuredText, cette dernière version est principalement destinée aux auteurs de documentation, aux traducteurs et aux personnes ayant des exigences de formatage particulières.

Pour plus d'informations sur la création de la documentation Python, reportez-vous à Doc/README.rst.

D'importantes modifications rétrocompatibles ont été apportées pour la version de Python 3.0, ce qui peut entraîner l'échec des programmes écrits pour Python 2 lorsqu'ils sont exécutés avec Python 3. Pour plus d'informations sur le portage de votre code de Python 2 vers Python 3, consultez le Porting HOWTO.

Pour tester l'interpréteur, tapez make test dans le répertoire de niveau supérieur. L'ensemble de test produit une sortie. Vous pouvez généralement ignorer les messages sur les tests ignorés en raison de fonctionnalités facultatives qui ne peuvent pas être importées. Si un message s'imprime à propos d'un test ayant échoué ou si un retraçage ou un vidage de mémoire est produit, quelque chose ne va pas.

Par défaut, les tests ne peuvent pas surexploiter des ressources telles que l'espace disque et la mémoire. Pour activer ces tests, exécutez make testall .

Si des tests échouent, vous pouvez réexécuter le(s) test(s) ayant échoué en mode détaillé. Par exemple, si test_os et test_gdb échouent, vous pouvez exécuter :

Si l'échec persiste et semble être un problème avec Python plutôt qu'avec votre environnement, vous pouvez déposer un rapport de bogue et inclure la sortie pertinente de cette commande pour montrer le problème.

Voir Exécution de tests d'écriture et d'écriture pour en savoir plus sur l'exécution de tests.

Sur les systèmes Unix et Mac, si vous avez l'intention d'installer plusieurs versions de Python en utilisant le même préfixe d'installation (argument --prefix du script de configuration), vous devez veiller à ce que votre exécutable python principal ne soit pas écrasé par l'installation d'une version différente. Tous les fichiers et répertoires installés à l'aide de make altinstall contiennent la version majeure et mineure et peuvent donc cohabiter. make install crée également $/bin/python3 qui fait référence à $/bin/pythonX.Y . Si vous avez l'intention d'installer plusieurs versions en utilisant le même préfixe, vous devez décider quelle version (le cas échéant) est votre version "principale". Installez cette version en utilisant make install . Installez toutes les autres versions en utilisant make altinstall .

Par exemple, si vous souhaitez installer Python 2.7, 3.6 et 3.10 avec 3.10 étant la version principale, vous devez exécuter make install dans votre répertoire de construction 3.10 et make altinstall dans les autres.

Les rapports de bugs sont les bienvenus ! Vous pouvez utiliser le traqueur de problèmes pour signaler des bogues et/ou soumettre des demandes d'extraction sur GitHub.

Vous pouvez également suivre les discussions de développement sur la liste de diffusion python-dev.

Si vous avez une proposition pour changer Python, vous pouvez envoyer un e-mail aux listes de diffusion comp.lang.python ou python-ideas pour un premier retour. Une proposition d'amélioration Python (PEP) peut être soumise si votre idée gagne du terrain. Tous les PEP actuels, ainsi que les directives pour soumettre un nouveau PEP, sont répertoriés sur python.org/dev/peps/.

Voir PEP 619 pour les détails de la version Python 3.10.

Copyright (c) 2001-2021 Python Software Foundation. Tous les droits sont réservés.

Copyright (c) 2000 BeOpen.com. Tous les droits sont réservés.

Copyright (c) 1995-2001 Corporation pour les initiatives nationales de recherche. Tous les droits sont réservés.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum. Tous les droits sont réservés.

Voir la LICENCE pour plus d'informations sur l'historique de ce logiciel, les termes et conditions d'utilisation et l'AVIS DE NON-RESPONSABILITÉ DE TOUTES GARANTIES.

Cette distribution Python contient non Code GNU General Public License (GPL), il peut donc être utilisé dans des projets propriétaires. Il existe des interfaces vers certains codes GNU, mais celles-ci sont entièrement facultatives.

Toutes les marques citées ici sont la propriété de leurs détenteurs respectifs.


Menus contextuels de niveau supérieur

Menu contextuel de la session en cours

Supprime tous les résultats de la liste Session en cours. Tous les ensembles de données en sortie auxquels les résultats font référence seront supprimés, ainsi que toute entité ou ensemble d'enregistrements en entrée (données créées à l'aide d'entité interactive ou d'entrée de ligne). Si vous choisissez Supprimer tout , une boîte de message s'ouvrira vous demandant si vous êtes sûr de vouloir supprimer toutes les données de sortie.

Supprime toutes les informations de résultat de la liste. Aucune donnée de sortie n'est supprimée.

Menu contextuel des sessions précédentes

Supprime tous les résultats de la liste Session précédente. Aucune donnée de sortie ne sera supprimée.

Menu contextuel Ne pas exécuter

Si vous quittez et enregistrez une carte alors que les outils sont en cours d'exécution ou en attente, tous les outils en cours d'exécution et en attente s'afficheront sous Non exécuté .

Supprime tous les résultats de la liste Non exécuté. Aucune donnée de sortie ne sera supprimée.

Exécute tous les outils. Les résultats sont supprimés de Non exécuté et ajoutés à la session en cours.

Partagé

Il n'y a pas de menu contextuel pour le nœud partagé.


Script de migration MySQL vers PostgreSQL

Je travaille sur un script Python pour migrer une base de données MySQL vers une base de données PostgreSQL avec un schéma différent (différentes structures de table, différents types de données, etc.).

Je suis un administrateur système et malheureusement je ne code pas très souvent. J'ai donc des doutes sur cette première phase de programmation.

Je commence par les tables qui sont faciles à migrer (presque la même structure), mais très bientôt je vais devoir transférer des tables qui nécessitent plus d'opérations à convertir pour la compatibilité.

Mon code ressemble en fait à ceci :

Comme vous le remarquerez, dans chaque section du script, la structure est presque la même :

  • Sélectionnez les données d'une table de la base de données source (mysql), le résultat est géré par un curseur avec indicateur de dictionnaire (un dictionnaire python).
  • Après cela, le dictionnaire est itéré dans une boucle for lorsque cela est possible, par ex. transtypage des champs, ou adaptez la structure du tableau (voir section : A2.right > A3.permission).
  • Et toujours à l'intérieur de la boucle for, chaque enregistrement est inséré dans la base de données de destination.

Questions/Doutes :

Dois-je créer une classe afin d'abstraire le code redondant ? Ou peut-être est-il préférable de simplement créer une fonction ? Quelqu'un peut-il poster un court exemple? Je n'ai aucune idée de comment procéder.
Dans les deux cas, je vois des problèmes à l'abstraire car le code redondant se trouve dans une boucle où je devrai effectuer différentes opérations en fonction de la table que j'itére.

J'avais l'habitude d'ouvrir et de fermer les curseurs à chaque opération (section script), puis j'ai décidé d'ouvrir les deux curseurs au début du script, de les utiliser jusqu'à la fin et de les fermer. Mais maintenant j'ai lu ceci et je suis confus. Quoi de mieux à votre avis ? Un curseur pour chaque opération, ou un curseur pour l'ensemble du script ?


4 réponses 4

J'utilise le package appelé yasnippet pour quelque chose de similaire à celui-ci. Après quelques modifications mineures, je l'ai adapté pour utiliser le style Google docstring à la place :

Notez cependant que cela nécessite une certaine configuration :

L'extrait lui-même doit exécuter un code élisp utilitaire pour générer le texte. Ceci est généralement résolu en créant un fichier appelé .yas-setup.el avec le code dans le répertoire d'extraits de code python-mode. Il est cependant également possible de placer le code quelque part dans votre .emacs à la place.

Le code de l'extrait est :

Le code du fichier .yas-setup.el est :

Notez que python-split-args est fourni par le la norme extraits. C'est-à-dire : https://github.com/AndreaCrotti/yasnippet-snippets/tree/master Vous les obtenez cependant par défaut lorsque vous installez le package via package.el .

Avec tout configuré correctement, vous devriez pouvoir écrire "defg" suivi de Tab pour développer l'extrait (voir l'image pour un exemple).

Il y a toujours un problème avec l'utilisation de cette indentation imbriquée à l'intérieur, par exemple, au sein de classes ou en tant que fonctions imbriquées. Dans ces cas, la docstring est indentée à tort un temps supplémentaire pour une raison quelconque. Je mettrai à jour ce post si j'arrive à résoudre ce problème.

L'extrait devrait maintenant fonctionner dans d'autres étendues en interdisant à yasnippet d'indenter automatiquement la deuxième extension.


9 réponses 9

Quelques réflexions qui me viennent à l'esprit, sans avoir réellement profilé votre code :

  1. Essayez de passer std::string comme référence à const pour éviter une copie (au cas où votre implémentation std::string n'est pas Copy-On-Write).
  2. Réservez de l'espace dans std::string en appelant reserve .
  3. Évitez d'appeler std::string::length à plusieurs reprises, mémorisez la valeur.
  4. Évitez d'indexer la chaîne à plusieurs reprises, utilisez plutôt un itérateur.

Pour ce que ça vaut, vous pouvez essayer une manière différente (plus fonctionnelle) d'implémenter cette fonction. Certains peuvent considérer cela idiomatique, d'autres auront du mal à lire. Votre appel -peut-être juste pour le plaisir, pour voir comment il fonctionne (n'oubliez pas d'activer les optimisations !) :

pour éviter les allocations lorsque vous faites le += .

Vous pouvez essayer ce code, mais je doute qu'il soit beaucoup plus rapide :

Notez que le paramètre in est maintenant passé par référence. Une amélioration possible, bien qu'improbable, serait de créer une table de recherche de 256 bools qui stocke si un caractère donné est alpha :

Notez que la LUT est remplie à chaque fois que ce code est appelé, si la chaîne est > 20.000, cette fois devrait être insignifiant cependant.

Vous pouvez essayer de suivre le code C++11 qui alloue de la mémoire et modifie la taille finale de la chaîne une seule fois

Voici une autre référence, montrant encore une autre possibilité qui peut valoir la peine d'être envisagée, si vous le pouvez :

Au moins dans mes tests, avec VC++ (10) et g++ (4.7.0), std::vector sort plus vite que string.

L'utilisation de notre propre version d'isalpha pilotée par table permet d'accélérer un peu par rapport à l'utilisation de ::isalpha , mais l'utilisation de std::vector améliore encore plus la vitesse, en particulier avec VC++ (bien que la différence soit équitablement substantiel avec g++ aussi).

Pour ceux qui aiment comparer les compilateurs, il convient de noter que g++ est non seulement plus rapide dans l'ensemble, mais aussi plus systématiquement rapide. Avec g++, le pire des cas n'est qu'environ deux fois plus lent que le plus rapide. Avec VC++, le pire des cas est environ trois fois plus lent.

Utilisez les paramètres régionaux C. Sur certains paramètres régionaux, isalpha et ses amis peuvent être très lents.

ou utilisez std::locale pour activer la locale C à partir du code

Pour un exemple de la façon dont les paramètres régionaux peuvent ralentir les performances, par ex. UNIX sort(1) par un facteur de 20x, voir cette ancienne réponse :

Parfois, il faut utiliser des repères.

Une solution C++ idiomatique est susceptible d'être mieux optimisée, les solutions d'Andrey et de Frerich sont donc toutes deux de solides concurrents.

Le code exposé ci-dessous donne les résultats suivants avec gcc 4.3.2 et -O2 :

Input1: "afoiahge m8hfw fewu8 n hv ghwvoiwbegh2390ty3t80ytgh8ghng8hg24u8b vh2vn289vh2gh28g9jfhfuweghwu2hbvgfw22ghb84ty2bgv2nfbukbvsdbvwuivbnbvbnn hf wgwg GWEV wgbv23t4 1sv4gbwer14hh414ernhe 01e4g 1E 1h4ghwerh14re e4hj 14yv y344yjd1vh h 1E6"

Input2 : la chaîne que vous avez proposée

De chez Andrey : 1 : 1243, 2 : 65469

De Frerich's : 1 : 1965, 2 : 140818

Par conséquent, la solution d'Andrey offre une accélération 2x solide par rapport à la solution proposée. Bien mieux.

Leur stratégie diffère cependant, car Andrey copie toute la chaîne d'un seul coup, puis supprime les parties qui ne correspondent pas, tandis que Frerich ne copie que les bonnes parties pour commencer.

Je choisirais l'approche de Frerich (bien qu'elle soit légèrement plus lente ici), juste pour éviter de grandes copies inutilisées si la mémoire est un problème. Notez que si vous avez une idée de la distribution, vous pouvez ajuster la quantité de mémoire réservée.

Essayez d'appeler reserve(2000) sur votre dernière chaîne avant de l'utiliser. Prenez également une référence const comme argument.

Je soupçonne que sur Unix, la fonction isalpha effectue beaucoup plus de travail pour prendre en charge Unicode, et vous n'êtes intéressé que par la gamme ASCII. C'est toujours un grand pas, mais vous pouvez essayer de le remplacer par une comparaison personnalisée, comme si ((in[i] <= 'Z' && in[i] >= 'A') || (in[i] >= 'a' && in[i] <= 'z')) .

Je suggère que ce n'est pas l'appel isalpha() qui prend le temps mais plutôt les deux appels std::string::operator[] et/ou l'appel std::string::operator+=.

Vous pourriez probablement accélérer cette boucle en utilisant un itérateur pour référencer dans , évitant ainsi std::string::operator[] , et l'ajout du caractère sera plus rapide en utilisant std::string::push_back et si vous développez initialement final pour avoir la même capacité initiale que dans .

Passer la chaîne d'entrée non modifiée en tant que référence const peut également aider, mais ne sera significatif que si vous appelez la fonction elle-même de manière itérative.

Cela dit, je suggère fortement que vous utilisiez le profileur ou que vous ajoutiez une instrumentation de synchronisation au code pour révéler le véritable porc de performance. Les horaires que vous suggérez ne semblent pas probables - quelque chose d'autre se passe ici, je pense.


Voir la vidéo: Integrating Deep Learning with ArcGIS using Python (Octobre 2021).