Запрос списка в стиле 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)
Есть ли способ выбрать отличные от $ коды и выбрать объекты, где тип равен 1? Как я могу использовать LINQ с PowerShell?
4 ответа
Что сказал Кит. Кроме того, изменил конструктор в своем C# и использовал параметр -Unique в командлете 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}
Для отличного использования Select-Object
командлет (с псевдонимом Select
) с параметром Unique, например:
PS> 1,2,3,4,4,2 | Select-Object -Unique
1
2
3
4
Для фильтрации используйте Where-Object
командлет (с псевдонимом Where
а также ?
):
PS> $codes | where {$_.Type -eq '1'}
Что касается LINQ, вы не можете использовать операторы LINQ в PowerShell, потому что PowerShell не поддерживает вызов универсальных методов.NET или статических методов расширения, которые оба имеют решающее значение для LINQ.
Примечание редактора: PSv3 + теперь поддерживает эти вещи.
Полезный ответ Дуга Финка и полезный ответ Кита Хилла покажут вам идиоматические аналоги PowerShell .Distinct()
а также .Where()
Методы LINQ.
В PowerShell v3 или выше вы теперь можете использовать LINQ.
Приведенное ниже решение демонстрирует, что LINQ можно использовать для решения вашей проблемы, но также показывает, что это несколько громоздко и, вероятно, стоит усилий, если вам нужны расширенные функции запросов и / или вопросы производительности.
# 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' }
)
Простой вопрос, простой ответ:
[Linq.Enumerable]::Distinct($codes)