Sé libre de divulgar nuestro espacio y códigos con tus amigos, necesitamos tu ayuda para aumentar esta comunidad.
Solución:
Merge-Hashtables
en lugar de eliminar keys podría considerar simplemente sobrescribirlos:
$h1 = @a = 9; b = 8; c = 7
$h2 = @b = 6; c = 5; d = 4
$h3 = @c = 3; d = 2; e = 1
Function Merge-Hashtables
$Output = @
ForEach ($Hashtable in ($Input + $Args))
If ($Hashtable -is [Hashtable])
ForEach ($Key in $Hashtable.Keys) $Output.$Key = $Hashtable.$Key
$Output
Para este cmdlet, puede usar varias sintaxis y no está limitado a dos tablas de entrada: Uso de la canalización: $h1, $h2, $h3 | Merge-Hashtables
Usando argumentos: Merge-Hashtables $h1 $h2 $h3
O una combinación: $h1 | Merge-Hashtables $h2 $h3
Todos los ejemplos anteriores devuelven la misma tabla hash:
Name Value
---- -----
e 1
d 2
b 6
c 3
a 9
Si hay algún duplicado keys en las tablas hash proporcionadas se toma el valor de la última tabla hash.
(Agregado 2017-07-09)
Merge-Hashtables versión 2
En general, prefiero funciones más globales que se pueden personalizar con parámetros para necesidades específicas como en la pregunta original: “sobrescribir key-valor pares en el primero si es el mismo key existe en el segundo”. ¿Por qué dejar que el último anule y no el primero? ¿Por qué eliminar nada en absoluto? Tal vez alguien más quiera fusionar o unir los valores u obtener el valor más grande o solo el promedio…
La versión a continuación ya no admite el suministro de tablas hash como argumentos (solo puede canalizar tablas hash a la función), pero tiene un parámetro que le permite decidir cómo tratar el valor array en entradas duplicadas operando el valor array asignado al hash key presentado en el objeto actual ($_
).
Función
Function Merge-Hashtables([ScriptBlock]$Operator)
$Output = @
ForEach ($Hashtable in $Input)
If ($Hashtable -is [Hashtable])
ForEach ($Key in $Hashtable.Keys) $Output.$Key = If ($Output.ContainsKey($Key)) @($Output.$Key) + $Hashtable.$Key Else $Hashtable.$Key
If ($Operator) ForEach ($Key in @($Output.Keys)) $_ = @($Output.$Key); $Output.$Key = Invoke-Command $Operator
$Output
Sintaxis
HashTable[] | Merge-Hashtables [-Operator ]
Por defecto
De forma predeterminada, todos los valores de las entradas de la tabla hash duplicadas se agregarán a un array:
PS C:> $h1, $h2, $h3 | Merge-Hashtables
Name Value
---- -----
e 1
d 4, 2
b 8, 6
c 7, 5, 3
a 9
Ejemplos
Para obtener el mismo resultado que la versión 1 (usando el últimos valores) utilice el comando: $h1, $h2, $h3 | Merge-Hashtables $_[-1]
. Si desea utilizar el primeros valores en cambio, el comando es: $h1, $h2, $h3 | Merge-Hashtables $_[0]
o la valores más grandes: $h1, $h2, $h3 | Merge-Hashtables ($_
.
Más ejemplos:
PS C:> $h1, $h2, $h3 | Merge-Hashtables Measure-Object -Average).Average # Take the average values"
Name Value
---- -----
e 1
d 3
b 7
c 5
a 9
PS C:> $h1, $h2, $h3 | Merge-Hashtables $_ -Join "" # Join the values together
Name Value
---- -----
e 1
d 42
b 86
c 753
a 9
PS C:> $h1, $h2, $h3 | Merge-Hashtables $_ # Sort the values list
Name Value
---- -----
e 1
d 2, 4
b 6, 8
c 3, 5, 7
a 9
Veo dos problemas:
- La riostra abierta debe estar en la misma línea que
Foreach-object
- No debe modificar una colección mientras enumera a través de una colección
El siguiente ejemplo ilustra cómo solucionar ambos problemas:
function mergehashtables($htold, $htnew)
foreach-object
$key = $_
if ($htnew.containskey($key))
$htold.remove($key)
$htnew = $htold + $htnew
return $htnew
No es una respuesta nueva, esto es funcionalmente igual que @Josh-Petitt con mejoras.
En esta respuesta:
Merge-HashTable
usa la sintaxis correcta de PowerShell si desea colocar esto en un módulo- No era idempotente. Agregué la clonación de la entrada HashTable, de lo contrario, su entrada fue golpeada, no fue una intención
- agregó un ejemplo apropiado de uso
function Merge-HashTable
param(
[hashtable] $default, # Your original set
[hashtable] $uppend # The set you want to update/append to the original set
)
# Clone for idempotence
$default1 = $default.Clone();
# We need to remove any key-value pairs in $default1 that we will
# be replacing with key-value pairs from $uppend
foreach ($key in $uppend.Keys)
if ($default1.ContainsKey($key))
$default1.Remove($key);
# Union both sets
return $default1 + $uppend;
# Real-life example of dealing with IIS AppPool parameters
$defaults = @
enable32BitAppOnWin64 = $false;
runtime = "v4.0";
pipeline = 1;
idleTimeout = "1.00:00:00";
;
$options1 = @ pipeline = 0; ;
$options2 = @ enable32BitAppOnWin64 = $true; pipeline = 0; ;
$results1 = Merge-HashTable -default $defaults -uppend $options1;
# Name Value
# ---- -----
# enable32BitAppOnWin64 False
# runtime v4.0
# idleTimeout 1.00:00:00
# pipeline 0
$results2 = Merge-HashTable -default $defaults -uppend $options2;
# Name Value
# ---- -----
# idleTimeout 1.00:00:00
# runtime v4.0
# enable32BitAppOnWin64 True
# pipeline 0
Aquí tienes las reseñas y calificaciones
Si te animas, puedes dejar una sección acerca de qué te ha parecido este escrito.