Il est audacieux d'affirmer que l'inefficacité (terme vague) d'AppleScript en est la cause. Bien sûr, cela pourrait très bien être un facteur, mais il est un peu gênant de dire que votre script est inefficace, et terriblement inefficace. Je ne sais pas si c'est le seulement La raison pour laquelle le script fonctionne lentement, mais c'est un bon endroit pour commencer à faire des corrections, que je vais décrire en extrayant les lignes problématiques dans votre code :
set myPeople to people
Redondant. Il n'est pas utile d'attribuer une valeur à une variable que vous n'avez pas l'intention d'utiliser de manière significative (par exemple, pour manipuler des données sans en modifier la source ou, si vous en avez vraiment besoin, pour rendre les scripts plus faciles à lire ou à déboguer). Nulle part ailleurs dans votre scripts vous ne faites référence à myPeople
à l'exception d'une autre ligne qui est également redondante. Par conséquent, ne gaspillez pas une opération (et potentiellement de la mémoire, mais pas vraiment dans ce cas particulier) en créant une variable dont vous n'avez pas besoin.
set numPeople to (count of myPeople)
Redondant en principe (je note que vous enregistrez la valeur de numPeople
bien qu'il ne soit utilisé que pour vous donner une référence d'index, que vous n'avez pas besoin de connaître ; voir le commentaire suivant).
repeat with i from 1 to numPeople
set myGuy to item i of myPeople
Ignorant pour un moment l'appel au journal qui fait référence à numPeople
Dans ce cas, l'objectif de la déclaration d'intention de l'Union européenne n'est pas atteint. numPeople
est de permettre l'itération dans une liste au moyen d'une variable compteur ( i
dans votre cas) qui est utilisé pour accéder à chaque élément par le biais de son index (position), c'est-à-dire item i of myPeople
. Il y a de nombreux cas où cela serait très approprié, mais c'est plus lent que de laisser AppleScript se préoccuper de la manière dont il accède aux éléments de la liste, ce qu'il peut faire en utilisant cette syntaxe : repeat with myGuy in people
set urlNum to count of personUrls
Redondant, pour la même raison que ci-dessus. Par ailleurs, je choisirais personnellement d'évaluer la taille d'une liste à l'aide de la fonction length
propriété. Cela ne s'applique pas aux listes imbriquées de listes pour lesquelles vous souhaitez inclure des éléments profondément imbriqués dans le nombre final, mais ce n'est pas le cas ici.
Dès qu'un script a évalué (récupéré) un objet, ses propriétés ont été récupérées dans le cadre de cette évaluation. length
est une propriété d'un objet liste, et sa valeur est simple, unaire (un integer
), de sorte que l'accès à cette valeur sera toujours rapide. count
est une commande. Elle effectue une ou plusieurs opérations non divulguées et renvoie une valeur. Je ne sais pas quelles sont ces opérations, et elles seront effectuées au niveau du langage C, donc probablement (presque certainement) ne ralentissent pas du tout ce script. Mais, en principe, c'est quelque chose à garder à l'esprit car il y a d'autres situations † une commande et une propriété font apparemment la même chose, mais la propriété est manifestement plus rapide.
† Je ne m'en souviens pas pour l'instant.
if urlNum > 0 then
Redondant, en principe. Il existe un else
Cette clause peut être conservée avec insistance, mais elle ne sert qu'à enregistrer le fait que rien n'a été fait. Si quelqu'un me demandait comment ralentir intentionnellement un script parce qu'il est tout simplement trop efficace, ce serait l'une de mes réponses.
repeat with j from urlNum to 1 by -1
Cette situation est signalée à la fois par l'utilisation d'une variable compteur, j
et pour sa position au sein de l'Union européenne. if
bloc. Si le urlNum
était fixé à 0, le cœur de la boucle de répétition ne serait jamais saisi et le script continuerait d'exécuter le code qui le suit. Mais, comme nous le verrons plus loin, l'ensemble du repeat
est redondant.
log ... (the label of item j of personUrls))
delete item j of personUrls
Je m'interroge sur la nécessité de cette mesure log
dans son ensemble. Il n'est certainement pas aussi autodestructeur que celui que j'ai mentionné plus haut, mais il remplit une fonction d'information et de sensibilisation. current date
et une recherche dans la base de données personUrls
objet de la liste.
- Dans les cas où vous avez besoin d'une variable compteur pour parcourir une liste, faites comme vous l'avez fait ci-dessus, et déclarez une variable à laquelle vous pouvez assigner la valeur de l'élément de la liste en cours, c'est-à-dire
set hisURL to item j of personalUrls
. En termes simples, chaque fois que vous demandez à AppleScript [la valeur de] item j of...
il doit accéder à l'objet liste et effectuer une recherche, ce qui est une opération relativement coûteuse. La déclaration d'une variable signifie que la recherche n'est effectuée qu'une seule fois, puis que la valeur (une copie de l'original) est stockée en mémoire, ce qui permet de la retrouver rapidement et facilement en termes de calcul.
Pour en revenir à la valeur enregistrée, sa valeur semble annulée par la suppression immédiate des données de l'URL. Je me demande si vous n'auriez pas simplement voulu un moyen de suivre où votre script était arrivé dans son exécution, ce qui n'a pas besoin d'être aussi compliqué. En utilisant vos variables de compteur, vous pourriez simplement : log [j, i]
(il suffit d'enregistrer leurs bornes supérieures une seule fois, puisque ces valeurs ne changent pas au cours d'une boucle).
En delete
dans le contexte de la boucle de répétition dans laquelle elle est appelée, va ralentir considérablement les choses. Vous itérez à travers tous dans une collection afin de la supprimer...
save
... puis vous enregistrez vos modifications. Comment puis-je faire en sorte que mon script s'exécute aussi lentement que possible ? J'effectuerais une opération de sauvegarde sur l'ensemble du carnet d'adresses un nombre de fois égal à numPeople * urlNum
. Cette valeur est au moins égale à 177, mais il s'agit en fait d'un multiple de cette valeur. Le nombre total de fois où vous devez exécuter la fonction save
J'imagine que l'opération serait 1.
Les effets d'entraînement :
Nous savons maintenant que l'itération sur PersonUrls
n'était pas nécessaire, l'ensemble de la repeat
peut être remplacé par la ligne : delete every url of myGuy whose...
.
- Il convient de garder à l'esprit que tout script comportant des éléments imbriqués de type
repeat
seront inefficaces : le nombre d'opérations effectuées est un produit de la taille de chaque liste.
Je note que vous mentionnez avoir tenté de supprimer en masse les URL d'un contact, ce qui n'a pas fonctionné pour vous, vous obligeant à le faire de manière itérative. Cependant, comme vous n'avez pas fourni de code montrant les méthodes que vous avez essayées pour effectuer la suppression en masse, il n'est pas possible de donner un aperçu de la raison pour laquelle cela a échoué pour vous.
Retrait de la repeat
a l'avantage cumulatif d'annuler le bloc parent if
indépendamment de mes commentaires antérieurs à ce sujet.
- Les conditionnelles peuvent être des expressions coûteuses à évaluer, en particulier si l'on en exécute 177 qui n'ont jamais été nécessaires.
Le code remanié :
En remontant le script, les déclarations de variables précédentes deviennent toutes redondantes, ce qui conduit à la conclusion finale que votre script entier est fonctionnellement équivalent à :
use application "Contacts"
tell (a reference to every person)
delete (its urls where the value contains "outlook")
set its note to missing value
end tell
save
Informations sur le système : Version AppleScript : 2.7 Version du système : 10.13.6
Et maintenant ?
Votre objectif ultime était-il de supprimer tous URL contenant "outlook", ou avez-vous prévu de conserver une URL "outlook" pour les contacts qui en disposent ?