Doug Finke's helpful answer and Keith Hill's helpful answer show you PowerShell-idiomatic analogs to the .Distinct()
and .Where()
LINQ methods.
In PowerShell v3 or higher you now can use LINQ.
The solution below demonstrates that LINQ can be used to solve your problem, but also shows that doing so is requires somewhat cumbersome syntax and is probably only worth the effort if you need advanced query features and/or performance matters.
- See this answer for a general overview of how to use LINQ from 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' }
)