在PowerShell中查询LINQ样式的列表

Var*_*ica 12 linq powershell

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)
Run Code Online (Sandbox Code Playgroud)

有没有办法从$ code中选择不同的并选择类型等于1的对象?如何在PowerShell中使用LINQ?

Kei*_*ill 26

为了明确使用带有Unique参数的Select-Objectcmdlet(别名Select),例如:

PS> 1,2,3,4,4,2 | Select-Object -Unique
1
2
3
4
Run Code Online (Sandbox Code Playgroud)

对于过滤使用Where-Objectcmdlet(别名为Where?):

PS> $codes | where {$_.Type -eq '1'}
Run Code Online (Sandbox Code Playgroud)

对于LINQ,您不能在PowerShell中使用LINQ运算符,因为PowerShell不支持调用对LINQ至关重要的通用.NET方法或静态扩展方法.

编者按:PSv3 +现在支持这些东西.


Dou*_*nke 17

基思说的是什么.另外,更改了C#中的构造函数,并在Sort cmdlet上使用了-Unique参数.

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}
Run Code Online (Sandbox Code Playgroud)


mkl*_*nt0 6

Doug Finke 的有用答案Keith Hill 的有用答案向您展示了 PowerShell 惯用的类似于.Distinct().Where()LINQ 方法类似的 PowerShell 惯用用法。

\n
\n

PowerShell v3 或更高版本中,您现在可以使用 LINQ

\n

下面的解决方案演示了 LINQ 可以用来解决您的问题,但也表明这样做需要一些麻烦的语法,并且可能只有在您需要高级查询功能和/或性能问题时才值得付出努力

\n
    \n
  • 有关如何从 PowerShell 使用 LINQ 的一般概述,请参阅此答案。
  • \n
\n
\n
# Create the type whose instances will make up the list to filter.\n# Make it implement IEquatable<T> with custom comparison logic that\n# compares property values so that the .Distinct() LINQ method works correctly.\nAdd-Type -TypeDefinition @"\n\n  public class pack_code : System.IEquatable<pack_code>\n  {\n      public string code { get; set; }\n      public string type { get; set; }\n\n      // IEquatable<T> interface implementation\n\n      // Test equality of this object with another of the same type.\n      public bool Equals(pack_code other) {\n        // Note: Normally, you\'d need to deal with the case of other == null as well.\n        return this.code == other.code && this.type == other.type;\n      }\n\n      // If Equals() returns true for a pair of objects  \n      // then GetHashCode() must return the same value for these objects.         \n      public override int GetHashCode() {\n        return this.code.Length + this.type.Length;\n      }\n  }\n\n"@\n\n# Create the list to filter.\n# Note:\n#  * Despite not having a constructor for [pack_code], PowerShell is smart\n#    enough to construct an instance from a cast from a hashtable that contains\n#    entries whose names match the settable [pack_code] properties.\n#  * The array of [pack_code] instances is then cast to the list type.\n#  * The list contains 3 objects of type 1, but only 2 distinct ones.\n$codes = [System.Collections.Generic.List[pack_code]] (\n           [pack_code] @{code = \'2\'; type = \'1\'},\n           [pack_code] @{code = \'3\'; type = \'5\'},\n           [pack_code] @{code = \'2\'; type = \'1\'},\n           [pack_code] @{code = \'1\'; type = \'1\'}\n         )\n\n# Invoke the LINQ methods as static methods of the \n# [System.Linq.Enumerable] type to\n# return all distinct objects whose type property is \xe2\x80\x981\xe2\x80\x99.\n# Note that the result will be an *iterator*; if you want a\n# static array, wrap the call in [Linq.Enumerable]::ToArray(...)\n[Linq.Enumerable]::Where(\n  [Linq.Enumerable]::Distinct($codes),\n  [Func[pack_code, bool]] { $Args[0].type -eq \'1\' }\n)\n
Run Code Online (Sandbox Code Playgroud)\n