Using LINQ in PowerShell with plinqo

Image Description

Daily PowerShell #20

Scripting Daily PowerShell DotNet

November 5, 2021

LINQ is a set of methods that are useful in .NET for working with arrays of objects. Using LINQ is difficult in PowerShell because it doesn’t work well with generic methods. plinqo provides methods that accept script blocks so LINQ methods are easily accessible in PowerShell.

You can learn how plinqo is developed by visiting our GitHub repository.

Install plinqo

plinqo is on the PowerShell Gallery and can be installed with Install-Module. You’ll need to import the module with Import-Module to get the plinqo class defined.

Install-Module plinqo    
Import-Module plinqo

Use plinqo

plinqo exposes a single plinqo class that you can pass your array into. Once in the plinqo class you can take advantage of methods like Where, First, and Skip.

$Array = 1..1000000
[plinqo]::new($Array).Where({$args[0] -gt 10000}).Skip(10).Take(100)

plinqo Methods

plinqo offers 20 different LINQ methods. In these examples we’ll be working with a simple array of 1 million integers.

$Array = 1..1000000

All

Returns $true if all the items in the array match the filter.

[plinqo]::new($Array).All({$args[0] -lt 2000000})

Any

Returns $true if any of the items in the array match the filter.

[plinqo]::new($Array).Any({$args[0] -eq 3000})

Average

Returns the average of the values in the array.

[plinqo]::new($Array).Average({$args[0]})

Concat

Combines two arrays together.

$Array2 = 1..1000
[plinqo]::new($Array).Concat($Array2)

Count

Counts the number of items in the array.

[plinqo]::new($Array).Count()

Distinct

Removes duplicates within the array.

$A = @(1,1,1,2,3,4)
[plinqo]::new($A).Distinct()

ElementAt

Returns the element at the index specified.

[plinqo]::new($Array).ElementAt(4)

Except

Returns items that do not match the specified array.

$Array2 = 1..10000
[plinqo]::new($Array).Except($Array2)

First

Returns the first item and throws an exception if the list is empty.

[plinqo]::new($Array).First()

FirstOrDefault

Returns the first item or $null if the array is empty.

[plinqo]::new($Array).FirstOrDefault()

Last

Returns the last item and throws an exception if the list is empty.

[plinqo]::new($Array).Last()

LastOrDefault

Returns the last item or $null if the array is empty.

[plinqo]::new($Array).LastOrDefault()

Select

Maps the items in the array and returns a new item based on the script block.

[plinqo]::new($Array).Select({$args[0] * 2})

Single

Returns a single item and throws an exception if the array contains more than one item.

[plinqo]::new($Array).Take(1).Single()

SingleOrDefault

Returns a single item or returns $null if the array is empty.

[plinqo]::new($Array).Take(1).SingleOrDefault()

Skip

Skips the specified number of items in the array.

[plinqo]::new($Array).Skip(100000)

Sum

Sums the items in the array

[plinqo]::new($Array).Sum()

Take

Takes the number of items specified in the array.

[plinqo]::new($Array).Take(20)

Where

Filers the array based on the script block.

[plinqo]::new($Array).Where({$args[0] -gt 999999})

Performance

plinqo is pretty fast. It’s about as fast as the where() method in PowerShell and much faster than Where-Object.

$Array = 1..1000000
Measure-Command {
    [plinqo]::new($Array).Where({$args[0] -gt 10000})
}

<#
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 766
Ticks             : 17665031
TotalDays         : 2.04456377314815E-05
TotalHours        : 0.000490695305555556
TotalMinutes      : 0.0294417183333333
TotalSeconds      : 1.7665031
TotalMilliseconds : 1766.5031
#>


Measure-Command {
    $Array.Where({$_ -gt 10000})
}

<#
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 632
Ticks             : 16328007
TotalDays         : 1.889815625E-05
TotalHours        : 0.00045355575
TotalMinutes      : 0.027213345
TotalSeconds      : 1.6328007
TotalMilliseconds : 1632.8007
#>

Measure-Command {
    $Array | Where-Object {$_ -gt 10000}
}

<#
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 5
Milliseconds      : 303
Ticks             : 53037798
TotalDays         : 6.13863402777778E-05
TotalHours        : 0.00147327216666667
TotalMinutes      : 0.08839633
TotalSeconds      : 5.3037798
TotalMilliseconds : 5303.7798
#>