Conseils pour jouer au golf dans PowerShell

45

Quels conseils généraux avez-vous pour jouer au golf dans Windows PowerShell? Je recherche des idées pouvant être appliquées aux problèmes de code de golf en général, qui sont au moins quelque peu spécifiques à PowerShell (par exemple, "supprimer les commentaires" n'est pas une réponse). Merci de poster un pourboire par réponse.

... pris presque textuellement de la question de Marcog .

Joey
la source
3
Quand j'ai googlé "PowerShell Golf", c'était le premier coup!
Matt

Réponses:

24

Pouvoirs de 10 littéraux avec notation scientifique:

4e6 = 4000000

Pouvoirs de 2 littéraux:

4KB = 4096
4MB = 4194304
4GB = 4294967296

# TB and PB suffixes also exist, but less useful for golf.

Pourrait être utile.

Joey
la source
19

Si vous devez exécuter une boucle et que vous savez exactement combien de fois elle doit être exécutée à chaque fois, envisagez de canaliser un tableau d'entiers contigus ForEach-Objectvia l' %alias au lieu d'utiliser for.

for($x=1;$x-le10;$x++){...}

contre

1..10|%{...}

Iszi
la source
18

Vous pouvez beaucoup ignorer les espaces dans PowerShell. Si vous sentez que cela n’est peut-être pas nécessaire, ce n’est peut-être pas le cas. Ceci est particulièrement utile dans les comparaisons.

Exemple:

$x-eq$i-and$x-ne9

contre.

$x -eq $i -and $x -ne 9

Si vous devez créer une branche dans votre script en fonction du résultat d'un test unique pouvant avoir plusieurs résultats, vous switchpouvez parfois associer ou surpasser une instruction if.

Exemple (commutateur vs. if / else - tie):

if($x%2-eq0){'even'}else{'odd'}

contre.

switch($x%2){0{'even'}1{'odd'}}

Ou (commutateur vs si / elseif / else - commutateur gagne par 15):

if($x%2-eq0){'even'}elseif($x%2-eq1){'odd'}else{'error'}

contre.

switch($x%2){0{'even'}1{'odd'}2{'error'}}

Si le commutateur est réellement basé sur certains résultats mathématiques, comme l'opération modulo ci-dessus, vous pouvez le remplacer entièrement par un tableau. Ici, il enregistre 13 caractères supplémentaires et est même plus court que l’instruction originale if / else à deux options. (Merci à Danko Durbic pour ce bit.)

('even','odd','error')[$x%2]

Si vous utilisez beaucoup une commande particulière, en particulier une sans alias abrégé préexistant, définissez un alias à caractère unique au début.

Exemple:

nal g Get-Random;g 10;g 10;g 10

contre.

Get-Random 10;Get-Random 10;Get-Random 10
Iszi
la source
('even','odd')[$x%2]FYI.
TheIncorrigible1
15

L'encapsulation de la commande qui définit une variable entre parenthèses vous permet de transmettre la définition de la variable directement à d'autres commandes.

Par exemple, vous pouvez définir $ x, puis $ y en fonction de la valeur de $ x d'un coup avec ceci:

$y=($x=1)+1

Au lieu de cela:

$x=1;$y=$x+1

Vous pouvez définir $ h et le sortir avec ceci:

($h='Hello World!')

Au lieu de cela:

$h='Hello World!';$h
Iszi
la source
1
Ceci est particulièrement utile pour appeler des méthodes sur des objets. ($x=New-Object Windows.Forms.Form).Controls.Add($t)
Orthographe
14

Un commutateur peut agir comme une boucle quand on lui donne un tableau. Par exemple:

$FooBarMeh='a','b','c'
switch ($FooBarMeh)
{
    'a'{'FOO'}
    'b'{'BAR'}
    default{'MEH'}
}

Est-ce que la sortie:

FOO
BAR
MEH

Je ne suis pas tout à fait sûr de savoir où cela sera utile, mais je m'attends à ce que ce soit utile pour quelqu'un quelque temps.

Iszi
la source
2
Il est pratique chaque fois que vous avez besoin d'un ForEach-Objectet de l' switchintérieur. Par exemple (dans le monde réel), le code est très utile pour écrire des analyseurs rapides de fichiers texte dans lesquels vous devez faire différentes choses en fonction de la regex avec laquelle une ligne correspond.
Joey
C'est ... sacrément bizarre. Un tableau ne devrait pas correspondre à un caractère, mais c'est le cas.
chat
@Joey C'est switch -File $pathpour
ça
Tout ce qui est analysé n'est pas nécessairement un fichier.
Joey
12

Remplacez [math]::powpar la multiplication. Au lieu de

[math]::pow($a,$b)

tu peux écrire

"$a*"*$b+1|iex

Cela fonctionne pour les exposants entiers> = 0.

Danko Durbić
la source
J'avais besoin de voir cette réponse pour comprendre iex... Alias ​​pourInvoke-Expression
HeatfanJohn
11

Les opérateurs de comparaison travaillent sur des collections de valeurs en renvoyant des valeurs correspondantes:

1..5 -gt 2

va céder 3, 4et 5. Dans certains cas, cela peut aider à économiser plus longtemps |?{$_...}.

-match est aussi un opérateur de comparaison.

Joey
la source
1
Notez que vous n'avez pas besoin d'espaces dans cet exemple1..5-gt2
Matt
1
Je sais; il s’agissait plus de montrer la technique. Les espaces sont dans une réponse séparée .
Joey
11

Utilisez des alias autant que possible. Il y a un tas d'utiles:

?        Where-Object
%        ForEach-Object
gu       Get-Unique
sort     Sort-Object
iex      Invoke-Expression
Joey
la source
11

Vous voulez trouver le maximum ou le minimum d'une collection de valeurs? A tenté

(...|measure -ma).Maximum

ou

(...|measure -mi).Minimum

déjà?

Il suffit de trier et d'utiliser le dernier ou le premier élément:

(...|sort)[-1]  # maximum
(...|sort)[0]   # minimum
Joey
la source
1
Et, si vous connaissez la longueur de la collection de valeurs et si elle est inférieure à 10 ...
wizzwizz4
@ wizzwizz4: Oh, les longueurs maximales peuvent souvent être utilisées de manière créative, pas nécessairement de 10 ans. Bien que pour ce cas particulier, je ne me souvienne pas d'un cas où cela aurait déjà aidé.
Joey
1
Je veux dire, si le dernier élément est connu pour être 0, 1, 2, 3, 4, 5, 6, 7, 8ou 9, il sauverait un octet pour écrire la longueur connue au lieu de -1.
wizzwizz4
10

Raccourcir les noms de propriété

Malheureusement, contrairement aux paramètres, les propriétés / méthodes (tout ce qui est accédé par un point .) ne peuvent généralement pas être réduites à leur forme non ambiguë.

Mais certaines cmdlets peuvent opérer sur les noms de propriété et prendre des caractères génériques, et il existe des ensembles de paramètres peu connus de %et ?qui peuvent être utiles.

Habituellement, nous transmettons un bloc de script et faisons référence à l'élément avec $_, mais il existe une autre forme de ceux-ci qui prend un nom de propriété et accepte un caractère générique.

$o|select Le*  
$o|%{$_.Length}

Avec une propriété comme celle-ci, .Lengthnous ne pouvons pas utiliser la magie v3 qui fonctionnerait normalement sur un tableau car il Lengths'agit d'une propriété du tableau lui-même. Les deux propriétés ci-dessus peuvent donc être utilisées pour obtenir les longueurs des membres individuels. Le selectvient dans un peu plus court.

Mais %peut prendre directement un nom de propriété et renvoyer cette valeur:

$a|% Length

Ce qui peut être raccourci avec des jokers. Le caractère générique doit être résolu en une seule propriété (ou méthode, à ce sujet plus tard), de sorte qu'il générera une erreur utile s'il ne le fait pas, indiquant exactement quels membres il pourrait résoudre.

Dans le cas de Length, Le*est généralement le plus court. Même sur une seule chaîne, cette méthode est plus courte d'un octet que la simple utilisation de la propriété.

$a.Length                # 9   #(doesn't work on array)
$a|%{$_.Length}          # 15
$a|% Le*                 # 8

Mais selon ce que vous faites avec cela, cela peut être pire. Vous pouvez le faire, $a.Length*5mais pour le faire avec l'expression du pipeline, vous devez l'envelopper ($a|% Le*)*5; Cela peut toujours valoir la peine si cela est contre un tableau, mais le fait est que ce n’est pas toujours approprié comme substitution directe.

Cela fonctionne aussi avec les méthodes, et vous pouvez laisser le ()nom complet de la même longueur, mais les mêmes restrictions que ci-dessus concernant le fait de devoir l’emballer. La méthode doit avoir une surcharge qui ne prend aucun paramètre (vous pouvez passer des arguments en les plaçant après le nom de la méthode, ce qui est très pratique):

$a.ToUpper()             # 12
$a|% *per                #  9

Avec des arguments:

'gaga'-replace'g','r'    # 21
'gaga'|% *ce g r         # 16

Ce ne sont pas strictement les mêmes en ce que le -replace opérateur effectue un remplacement d'expression régulière, mais si vous remplacez simplement une chaîne, il peut (maintenant) être plus court pour utiliser la méthode; il est utile que les chaînes soient des arguments d'applets de commande plutôt que des arguments de méthodes, de sorte qu'elles n'ont pas besoin d'être citées.

Propriétés Where-Object

?peut également prendre des noms de propriété (partiels) et y appliquer un "opérateur" (sous la forme de paramètres de commutateur). Là encore, cela peut être plus court que d'utiliser l' Where-Objectapproche scriptblock standard si le nom de la propriété est suffisamment long et unique.

$a|?{$_.Length-gt5}      # 19
$a|? Le* -GT 5           # 14

($a|% Le*)-gt5           # 14 - Lengths, not objs
briantiste
la source
1
Un des rares endroits où les espaces sont nécessaires. Belle trouvaille, cependant. Je peux penser à plusieurs domaines où cela raccourcira les choses.
AdmBorkBork
Bien éditer Joey! Merci.
Briantist
Vous avez trouvé un moyen de le raccourcir ;-) ... ce qui est triste, c'est que dans l'ensemble, il s'agit à nouveau d'un pipeline, ce qui limite un peu son utilité. Ou plutôt, il y a beaucoup d'endroits où il faudrait à nouveau le mettre entre parenthèses pour obtenir une expression. Mais peu de techniques de golf sont sans compromis ...
Joey
1
@ConnorLSW ah oui je voulais mettre à jour ceci car je réalisais depuis que vous pouviez passer des arguments de cette façon, ce qui augmente grandement son utilité. Excellent usage de .ToString()!
Briantist
2
@briantist, cela a transformé PowerShell en un langage beaucoup plus compétitif, élimine vraiment certains des appels .Net inquiétants.
Colsw
9

Trouver une somme sur le long chemin:

(...|measure -s).Sum

Un moyen plus court:

...|%{$s+=$_};$s

Et même plus court:

...-join'+'|iex
Joey
la source
9

Les points-virgules et les sauts de ligne sont interchangeables. Le code de golf est souvent plus lisible s’il n’est pas inséré dans une seule ligne. Et la longueur est toujours la même (à condition que vous utilisiez U + 000A comme saut de ligne que PowerShell gère sans problèmes).

Joey
la source
2
Attendez, nous sommes inquiets pour la lisibilité?!
Kevin Cox
4
Si cela n'a pas d'effet sur la longueur ... pourquoi pas?
Joey
Cela ne fait-il pas techniquement une différence, car un point-virgule est un caractère de moins que \ r \ n? Seulement sous Unix, c’est un singulier \ n.
Vasili Syrakis
2
@Vasili: Vous pouvez enregistrer les fichiers sans problème avec seulement U + 000A entre les lignes. PowerShell ne se plaindra pas. Ce que j'ai déjà écrit dans la réponse, d'ailleurs. Les sauts de ligne sont une propriété du fichier et non du système d'exploitation sur lequel il est utilisé. Personne ne dit que vous ne pouvez pas utiliser les fins de ligne Unix sous Windows.
Joey
@ Joey Si vous avez utilisé une nouvelle installation de Windows pour faire de la programmation rapide, vous remarquerez que le Bloc-notes ne joue pas bien avec \ x0a
Stan Strum
9

Le Getverbe est impliqué. Cela peut raccourcir tout Get-Frobà juste Frob. Les prétendants fréquents sont dateou random.

Notez que cela ne fonctionnera pas correctement dans certains cas car vous pourriez avoir des utilitaires GNU dans votre chemin (ou d’autres programmes natifs qui s’entrechoquent). Dans ce cas, l'ordre de recherche semble préférer le programme natif avant qu'il ne considère les cmdlets avec les éléments Get-supprimés:

PS Home:\> date

Freitag, 15. November 2013 07:13:45


PS Home:\> $Env:Path += ';D:\Users\Joey\Apps\GnuWin32\bin'
PS Home:\> date
Fr Nov 15 07:14:13 W. Europe Standard Time 2013
Joey
la source
Cela ne veut pas tout à fait travailler toujours comme prévu. J'ai un script qui commence par nal g Get-Randomsauvegarder les personnages plus tard. En le changeant ennal g Random changez en, le script se bloque indéfiniment (ou, du moins, prend un temps démesuré à traiter - je n'ai pas eu la patience d'attendre la fin, mais cela prend plusieurs ordres de grandeur plus longtemps que la forme d'origine. avant d’avorter).
Iszi
2
Deux Measure-Commandinvocations courtes (100 fois Get-Randomcontre random) me disent que c'est environ 500 fois plus lent. Pour être honnête, je ne le savais pas auparavant. Mais il est bon de garder cela à l'esprit, en particulier dans les boucles avec de nombreuses itérations. Cela étant dit, le code golfé devrait être court, pas rapide ( cela dit, ça craint de devoir attendre deux jours pour obtenir une réponse à un problème de Project Euler).
Joey
1
Mon problème était d'exécuter 10 000 itérations du scénario de Monty Hall, chacune nécessitant trois itérations de Get-Random. Une augmentation de 50 000% du temps de traitement, multiplié par 30 000 exécutions, est plutôt désagréable.
Iszi
Sensationnel. Il semble que ce soit la même chose pour n'importe quel alias. Testé Get-Variablecontre gvet obtenu une comparaison similaire.
Iszi
1
Cela pourrait être ça. J'ai fait quelques calculs et je me suis dit que mon scénario de Monty Hall devrait prendre environ une heure et demie (normalement, 10 à 11 secondes) pour fonctionner sans Get-. Il s’agit là d’un assez lourd gonflement en temps d’exécution pour une économie de seulement 4 caractères.
Iszi
8

for Les boucles peuvent avoir n'importe quoi entre 0 et trois déclarations dans leur en-tête:

Boucle sans fin:

for(){}

Boucle avec initialisation:

for($n=0){}

Boucle avec initialisation et condition de fin:

for($n=0;$n-lt7){}

Dans de tels cas, les points-virgules supplémentaires à la fin peuvent être omis (c'est explicitement indiqué dans la spécification du langage). , il ne s'agit donc pas d'un détail d'implémentation), contrairement aux langages de type C qui exigent toujours exactement trois instructions.

Cela fait aussi whileun peu plus court. Comparer

while(...){}

et

for(;...){}

Avec le bonus supplémentaire que vous pouvez coller dans une ligne précédente (s'il en existe une) dans le foraussi bien sans frais supplémentaires (et même en sauvant un personnage).

Joey
la source
8

Si vous assignez un tableau dont vous savez qu'il n'aura que deux valeurs, n'utilisez pas d'indexation.

Quelque chose comme ça:

$a="apple","orange"
$a[0] # apple
$a[1] # orange

Peut facilement être transformé en ceci:

$a,$o="apple","orange"
$a # apple
$o # orange

Cela peut aussi être utile si vous avez juste besoin du premier élément d'un tableau:

$a,$b=1..10
$a # 1
$b # 2..10
SomeShinyMonica
la source
Dans ce cas (avec les chaînes) $a="apple";$o="orange"est de longueur identique. Ce sont les tableaux les plus longs qui peuvent parfois être assez bien optimisés, par exemple en plaçant tous les éléments dans une chaîne avec un séparateur, puis en utilisant -split(il est préférable d’utiliser (utiliser l’espace comme séparateur, car alors le unaire -splitsuffira).
Joey
8

Casting à la chaîne:

[string]$x

contre.

"$x"

La conversion en chaîne de cette manière peut également être utilisée pour aplatir un tableau de chaînes au lieu de le joindre:

$a = @('a','b','c')
$a -join ' '

contre.

$a = @('a','b','c')
"$a"

Conversion d'une chaîne en un type numérique:

[int]$x     [float]$x

contre.

+$x

Il est également très utile de savoir que PowerShell utilise toujours le type de l'opérande gauche pour déterminer le type final d'une expression et les conversions à appliquer:

'1'+2    -> '12'
1+'2'    -> 3

ce qui peut aider à déterminer où se trouvent les moulages inutiles.

Joey
la source
6

N'oubliez pas que vous n'avez pas toujours besoin de fournir le nom complet d'un paramètre. Certains paramètres sont positionnels.

Get-Random -InputObject (0..10)

... peut être coupé pour ...

Get-Random -I (0..10)

... parce que "I", dans ce cas, est suffisant pour identifier InputObjectde manière unique les autres paramètres valides pour cette commande.

Vous pouvez le couper plus loin pour ...

Get-Random (0..10)

... car InputObjectest un paramètre de position.

La tuyauterie est généralement plus courte que l'alimentation d'objets en tant que paramètre, en particulier lorsqu'elle peut supprimer le besoin de parenthèse. Coupons encore plus notre générateur de nombres aléatoires ...

0..10|Get-Random

Recherchez également d’autres moyens d’accomplir la même chose, même si vous ne pouvez pas modifier la commande. Pour le cas ci-dessus, vous pouvez faire ceci:

Get-Random 11

Ou, incorporant une autre suggestion *:

Random 11

** Remarque: L'omission Get-d'un nom de commande peut alourdir le temps d'exécution d'environ 50 000%. Pas mal si vous n’avez besoin que de la commande une fois, mais faites attention de ne pas l’utiliser avec de longues boucles. *

Et c’est comme cela que l’on peut faire tomber une simple commande au tiers de sa taille.

Iszi
la source
6

Faux opérateur ternaire. Vous pouvez attribuer directement à partir d'une ifdéclaration:

$z=if($x-eq$y){"truth"}else{"false"}

Mais vous pouvez utiliser un tableau à 2 éléments et utiliser le test pour y indexer. Les résultats de $ falsey reçoivent l'élément 0, les résultats de la vérité $ prennent l'élément 1:

$z=("false","true")[$x-eq$y]

NB qu'il s'agisse bien d'une indexation sur un tableau, et si le test donne une valeur pouvant être convertie en un entier, vous demanderez un élément situé en dehors des limites du tableau et obtiendrez $ null en retour, et vous devrez le faire !(test)pour forcer jette le résultat dans un bool, avec les options inversées.

TessellatingHeckler
la source
Le premier extrait n'a pas fonctionné à un moment donné (versions antérieures de PowerShell), si je me souviens bien, rendant nécessaire de l'envelopper dans $(). Il existait essentiellement une distinction entre l'utilisation de pipelines à partir de commandes et d'instructions en tant qu'expressions. On dirait que cela a déjà été fait, du moins dans PowerShell 5.
Joey,
En outre, si les éléments du tableau sont non statiques, ils sont tous deux analysés et traités dans le cadre de la création du tableau avant l'indexation et le résultat est attribué. Par exemple .
AdmBorkBork
6

Lorsque vous utilisez un nombre en tant qu'argument d'un opérateur qui nécessiterait sinon une chaîne, vous pouvez utiliser le nombre directement. Comparer

...-join'0'

contre.

...-join0

Fonctionne avec -splitaussi bien. L'argument est toujours d'abord converti en chaîne.

Joey
la source
Pour référence, cela fonctionne -replaceaussi bien.
AdmBorkBork
-replacefonctionne également sans deuxième argument lorsque vous souhaitez supprimer des allumettes,
Joey
5

Valeur absolue

Avec

$n=-123

Au lieu de

[math]::abs($n)

utilisation

$n-replace'-'

Bien entendu, les économies sont annulées si des parenthèses sont nécessaires.

Rynant
la source
Ou si vous avez besoin du résultat sur le côté gauche d'un opérateur ;-)
Joey
5

Si vous devez faire taire les erreurs, la variante évidente serait

try{ <# something that throws errors #> }catch{}

Cependant, c'est beaucoup trop long. Une variante plus courte consiste à exécuter le trybloc en tant que bloc de script et à rediriger simplement les erreurs dans une variable non définie (ce $nullserait la variable habituelle, mais celle-ci est encore trop longue):

.{ <# something that throws errors #> }2>$x

Cela économise cinq précieux octets (si ce n'est le monde).

Joey
la source
5

Utiliser la $ofs variable spéciale pour changer le O utput F ield S eparator utilisé lorsque stringifying un tableau. Utile si vous devez transformer des tableaux en chaînes plusieurs fois.

Par exemple:

$a=1,2,3,4
$a-join',';$a-join','
$ofs=',';"$a";"$a"

Enregistre 2 + n caractères sur le 2e -join, où n est la longueur du séparateur, et enregistre 5 + n supplémentaires pour le 3e -joinet ensuite.

AdmBorkBork
la source
1
Malheureusement très rarement utile (du moins dans mon parcours de golf jusqu'à présent - j'ai tendance à le réduire à une seule jointure à la fin).
Joey
5

Les variables automatiques ont des booléens pour True et False au fur $trueet à mesure , $falsemais vous pouvez obtenir des résultats similaires en utilisant l'opérateur non logique !et les entiers 0 et 1 (ou tout autre entier non nul.)

PS C:\Users\matt> !1
False

PS C:\Users\matt> !0
True

Presque toutes les expressions PowerShell peuvent être évaluées en tant que booléens. Donc, tant que vous savez comment certaines données sont évaluées, vous pouvez obtenir des booléens sans jamais avoir besoin de les diffuser explicitement. Soyez conscient de la valeur LHS lorsque vous effectuez ces opérations.

  • L'entier 0 est faux et les entiers non nuls sont évalués à vrai.
  • les chaînes de longueur non nulle sont vraies et les chaînes vides ou nuls (et les chaînes elles-mêmes) sont fausses.

Il y a d'autres exemples mais vous pouvez facilement tester en faisant un casting

PS C:\Users\matt> [bool]@(0)
False
Mat
la source
1
De nombreux autres types de données ont également un statut similaire. Les variables non initialisées par défaut $nullsont Falsey. La chaîne vide (et les variables définies sur la chaîne vide) sont falsey. Etc. Ceci peut ensuite être utilisé pour raccourcir l'indexation dans un tableau (par exemple, lors de l' exécution d' un if/ else), comme c'était le cas dans FizzBuzz .
AdmBorkBork
@TimmyD Très vrai. L'utilisation de ints est juste plus courte
Matt
@TimmyD Je voulais répondre à fizzbuzz jusqu'à ce que je voie le vôtre .... Je ne peux pas battre ça .... du moins pas encore
Matt
Notez que dans de nombreux cas, vous n'avez pas réellement besoin d' un bool. Vous pouvez utiliser 0et 1tout aussi bien. Les conversions implicites aident beaucoup à cet égard (que vous pouvez souvent forcer avec certains opérateurs).
Joey
4

Invoke-Expressionet Get-Randompeut également obtenir une entrée de pipeline au lieu d'arguments.

Pour iexcela permet d'enregistrer entre parenthèses sur certaines expressions:

iex 1..5-join'+'   # won't work
iex(1..5-join'+')  # does work, but has extra parentheses
1..5-join'+'|iex   # doesn't need the parentheses

Dans le cas randomcontraire, cela permet d’optimiser un peu le cas commun:

random -mi 10 31   # gets a random integer between 10 and 30
10..30|random      # much better :-)
(random 21)+10     # if needed in another expression that doesn't require extra
                   # parentheses

Cette dernière façon de l'utiliser sélectionne simplement un élément dans une liste. L' -cargument peut être donné pour permettre plus d'une sélection.

Joey
la source
4

Envisagez de stocker des blocs de script répétés dans des variables, au lieu d'utiliser des fonctions.

J'allais l'utiliser pour enregistrer des caractères dans mon implémentation Rock, Paper, Scissors avant de réaliser que réécrire la fonction sous forme de variable rendait même la variable inutile. Cela pourrait néanmoins être utile pour d’autres scripts, où vous exécutez le même code plusieurs fois.

function Hi{echo 'Hello, World!'};Hi

contre.

$Hi={echo 'Hello, World!'};&$Hi
Iszi
la source
2
Utile pour les fonctions qui ne prennent pas d'arguments. Sinon, params(...)cela prend plus de place que la définition de fonction n'enregistre. Connexes: Utilisez filterplus functionquand vous pouvez le faire.
Joey
Vous pouvez utiliser $argspour éviter le besoin de params; c'est-à-dire $x={$args[0]+2}(ou même $x={2+"$args"}); peut sauver un personnage ou 2 dans certaines circonstances. Vous pouvez également combiner cela avec une autre astuce pour plusieurs paramètres:$x={$a,$b=$args;$a+$b+3}
JohnLBevan
4

Vous pouvez utiliser à la $s|% t*yplace [char[]]$spour diviser une chaîne en tableau de caractères. D'après la réponse de TessellatingHeckler :% t*y étend à | ForEach-Object -Method ToCharArrayéquiv. de"$args".ToCharArray()

Par exemple, comparez

$s|% t*y

et

[char[]]$s

et

$s.ToCharArray()

C'est utile avec $argssurtout:$args|% t*y

mazzy
la source
1
C'est plutôt chouette. J'ai déjà utilisé le %truc pour les membres plusieurs fois, mais la plupart de mes golfs sont antérieurs à cette caractéristique ;-). C'est aussi une technique assez générale: essayez de trouver une combinaison lettre / caractère générique qui corresponde à la propriété / méthode dont vous avez besoin (et qui est plus courte que la réalité).
Joey
Autres exemples utiles tirés de la réponse: $s|% *perpour $s.toUpper()et $s|% *werpour $s.toLower(). Je suis d'accord que c'est assez chouette.
mazzy
Un autre exemple : |% t* "ddd\:hh\:mm\:ss"pour[TimeSpan].toString("ddd\:hh\:mm\:ss")
mazzy
Eh bien, ce n'est qu'un gaspillage de citations, alors; vous n'en avez pas besoin ici :-)
Joey
3

Utiliser la logique booléenne à la place des if-counters dans une boucle

Supposons que vous ajoutiez tous les nombres pairs de 1 à 10 ... 2+4+6+8+10=30

1..10|%{if($_%2-eq0){$o+=$_}};$o

Vous pouvez utiliser la négation booléenne pour la raccourcir à

1..10|%{if(!($_%2)){$o+=$_}};$o

pour sauvegarder un octet, mais que diriez-vous d'utiliser plutôt le transtypage implicite de Booléens en entiers, et d'insérer le conditionnel dans l'accumulateur

1..10|%{$o+=$_*!($_%2)};$o

Enregistre 6 octets dans cet exemple.

AdmBorkBork
la source
2
Jésus Christ. Je prévois de faire cela dans mon code de production au travail, mes collègues vont m'aimer beaucoup pour ça.
Chavez
3

La conversion de nombres à virgule flottante en nombres entiers dans PowerShell est un peu un champ de mines. Par défaut, la conversion arrondit les banquiers, ce qui ne coupe pas toujours la décimale et ne laisse pas le nombre entier le plus petit, ou arrondit toujours le chiffre 5 au chiffre suivant, comme cela se fait de façon décontractée, elle arrondit même l’un dans l’autre et l’autre avec un autre être surprenant, par exemple

PS C:\> [int]1.5
2

PS C:\> [int]2.5
2

et briser les calculs de code-golf. De nombreux autres langages courants effectuent des arrondissements par troncature, c'est pourquoi les questions de golf nécessitent souvent une troncature. Vous pourriez atteindre pour[Math]::Floor() meilleure chose à faire peut-être, mais attention, cela ne se comporte que de la même manière que la troncature pour les nombres positifs, mais que les nombres négatifs sont plus bas - plus loin de zéro. [Math]::Truncate()C’est ce dont vous avez besoin pour aligner le comportement de PS sur les arrondis par défaut des autres langues, mais il faut beaucoup de caractères.

Le remplacement des chiffres par une expression régulière après la virgule décimale peut vous aider à enregistrer quelques caractères:

[Math]::Truncate(1.5)
[Math]::Floor(1.5)
1.5-replace'\..*'

[Math]::Truncate($a)
[Math]::Floor($a)
$a-replace'\..*'
$a.split('.')[0]        # literal character split, not regex pattern split
TessellatingHeckler
la source
3

Inverser un tableau

Est utile dans beaucoup de défis où la sortie est reflétée d'une manière ou d'une autre.

Supposons que vous ayez

$a=1,2,3,4,5

La méthode d'inversion traditionnelle est longue, ennuyeuse et ne laisse pas la matrice sur le pipeline pour une utilisation immédiate.

[array]::reverse($a)

L'indexation directe dans le tableau en ordre inverse économise quelques octets, car les résultats sont conservés dans le pipeline, mais restent assez longs:

$a[($a.count-1)..0]

Au lieu de cela, essayez une boucle

$a|%{$a[-++$i]}
AdmBorkBork
la source
l'indexation inversée fonctionne bien lorsqu'il y a une limite supérieure pour le décompte
Joey
3

À partir de PowerShell Core 6, vous pouvez également utiliser des plages pour les caractères:

'a'..'z'

qui peut remplacer le beaucoup plus lourd

0..25|%{[char]($_+97)}
Joey
la source
Oh, ça va venir si pratique.
AdmBorkBork
1
[char[]](65..90)est également un moyen pratique de générer l'alphabet
Veskah