2010-05-19 14 views
9
add-type -Language CSharpVersion3 -TypeDefinition @" 
    public class pack_code 
    { 
     public pack_code() {} 

     public string code { get; set; } 
     public string type { get; set; } 
    } 
"@ 

$a = New-Object pack_code 
$a.code = "3" 
$a.type = "5" 
$b = New-Object pack_code 
$b.code = "2" 
$b.type = "5" 
$c = New-Object pack_code 
$c.code = "2" 
$c.type = "5" 
$d = New-Object pack_code 
$d.code = "1" 
$d.type = "1" 

$codes = New-Object 'System.Collections.Generic.List[object]' 
$codes.add($a) 
$codes.add($b) 
$codes.add($c) 
$codes.add($d) 

¿Hay alguna forma de seleccionar códigos distintos de $ y seleccionar los objetos donde type es igual a 1? ¿Cómo puedo usar LINQ con PowerShell?Consultar una lista LINQ-style en PowerShell

Respuesta

16

Lo que dijo Keith. Además, cambió el constructor en su C# y usó el parámetro -Unique en el cmdlet Sort.

Add-Type -Language CSharpVersion3 -TypeDefinition @" 
    public class pack_code 
    { 
     public pack_code(string code, string type) { 
      this.code=code; 
      this.type=type; 
     } 

     public string code { get; set; } 
     public string type { get; set; } 
    } 
"@ 

$codes = New-Object 'System.Collections.Generic.List[object]' 
$codes.Add((New-Object pack_code 3, 5)) 
$codes.Add((New-Object pack_code 2, 5)) 
$codes.Add((New-Object pack_code 2, 5)) 
$codes.Add((New-Object pack_code 1, 1)) 
$codes.Add((New-Object pack_code 2, 2)) 
$codes.Add((New-Object pack_code 2, 1)) 
$codes.Add((New-Object pack_code 2, 1)) 

$codes | sort code, type -Unique | where {$_.type -eq 1} 
26

Para uso distinto del Select-Object cmdlet (alias a Select) con el parámetro único, por ejemplo:

PS> 1,2,3,4,4,2 | Select-Object -Unique 
1 
2 
3 
4 

Para el filtrado usar el cmdlet Where-Object (alias de Where y ?):

PS> $codes | where {$_.Type -eq '1'} 

Como para LINQ, no puede usar operadores LINQ en PowerShell porque PowerShell no admite la invocación de métodos .NET genéricos o métodos de extensión estáticos que son cruciales para LINQ.

Nota del editor: PSV3 + ahora lo hace apoyo esas cosas.

1

simple pregunta, una respuesta sencilla:

[Linq.Enumerable]::Distinct($codes) 
+0

Eso es prometedor, pero como está escrito el código no funcionará, porque falta la lógica de comparación personalizada con el fin de reconocer a duplicar '[] pack_code instancias'; en otras palabras: su llamada es una no-operación efectiva. – mklement0

0

Doug Finke's helpful answer y Keith Hill's helpful answer se muestran análogos PowerShell-idiomáticas a los métodos de LINQ .Distinct() y .Where().


En v3 PowerShell o superior ahora puede utilizar LINQ.

La solución a continuación demuestra que LINQ se puede utilizar para resolver su problema, sino que también muestra que hacerlo es algo engorroso y es probablemente sólo vale la pena el esfuerzo si necesita funciones de búsqueda avanzada y/o importa el rendimiento.

  • Consulte this answer mío para obtener una descripción general de cómo usar LINQ de PowerShell.

# Create the type whose instances will make up the list to filter. 
# Make it implement IEquatable<T> with custom comparison logic that 
# compares property values so that the .Distinct() LINQ method works correctly. 
Add-Type -TypeDefinition @" 

    public class pack_code : System.IEquatable<pack_code> 
    { 
     public string code { get; set; } 
     public string type { get; set; } 

     // IEquatable<T> interface implementation 

     // Test equality of this object with another of the same type. 
     public bool Equals(pack_code other) { 
     // Note: Normally, you'd need to deal with the case of other == null as well. 
     return this.code == other.code && this.type == other.type; 
     } 

     // If Equals() returns true for a pair of objects 
     // then GetHashCode() must return the same value for these objects.   
     public override int GetHashCode() { 
     return this.code.Length + this.type.Length; 
     } 
    } 

"@ 

# Create the list to filter. 
# Note: 
# * Despite not having a constructor for [pack_code], PowerShell is smart 
# enough to construct an instance from a cast from a hashtable that contains 
# entries whose names match the settable [pack_code] properties. 
# * The array of [pack_code] instances is then cast to the list type. 
# * The list contains 3 objects of type 1, but only 2 distinct ones. 
$codes = [System.Collections.Generic.List[pack_code]] (
      [pack_code] @{code = '2'; type = '1'}, 
      [pack_code] @{code = '3'; type = '5'}, 
      [pack_code] @{code = '2'; type = '1'}, 
      [pack_code] @{code = '1'; type = '1'} 
     ) 

# Invoke the LINQ methods as static methods of the 
# [System.Linq.Enumerable] type to 
# return all distinct objects whose type property is ‘1’. 
# Note that the result will be an *iterator*; if you want a 
# static array, wrap the call in [Linq.Enumerable]::ToArray(...) 
[Linq.Enumerable]::Where(
    [Linq.Enumerable]::Distinct($codes), 
    [Func[pack_code, bool]] { $Args[0].type -eq '1' } 
) 
Cuestiones relacionadas