ruslander
ruslander

Reputation: 3875

What is the Linq.First equivalent in PowerShell?

The snippet below detects from a list of files which of them is a Directory on Ftp

as C# it will be like below

var files = new List<string>(){"App_Data", "bin", "Content"};
var line = "drwxr-xr-x 1 ftp ftp              0 Mar 18 22:41 App_Data"
var dir = files.First(x => line.EndsWith(x));

How I can transalte the last line in PowerShell ?

Upvotes: 62

Views: 32760

Answers (5)

KyleMit
KyleMit

Reputation: 30067

There is a native way to do this using the Powershell Array's Where Function by passing in a WhereOperatorSelectionMode like this:

(1..9).Where({ $_ -gt 3}, "First") # 4

You can also use the mode straight from the enum as well:

$mode = [System.Management.Automation.WhereOperatorSelectionMode]::First
(1..9).Where({ $_ -gt 3}, $mode) # 4

Using any of the values from the WhereOperatorSelectionMode enum

Name Val Description
Default 0 Return all items
First 1 Return the first item
Last 2 Return the last item
SkipUntil 3 Skip items until condition is true
Until 4 Return all items until condition is true
Split 5 Return an array of two elements

See Also: Checking Out The Where and ForEach Operators in PowerShell V4

Upvotes: 2

Robert Groves
Robert Groves

Reputation: 7748

Something like this...

$files = @("App_Data", "bin", "Content")
$line = "drwxr-xr-x 1 ftp ftp              0 Mar 18 22:41 App_Data"
$dir = $files | Where { $line.EndsWith($_) } | Select -First 1

These versions of the last line would all accomplish the same:

$dir = @($files | Where { $line.EndsWith($_) })[0]

$dir = $files | Where { $line.EndsWith($_) } | Select -index 0

$dir = $files | Where { $line.EndsWith($_) } | Select -First 1

It was pointed out that the above is not exactly equivalent in behavior to Linq.First because Linq.First throws exceptions in two cases:

  • Throws ArgumentNullException when source or predicate is null.
  • Throws InvalidOperationException when source sequence is empty or no element satisfies the condition in predicate.

If you wanted that behavior exactly, you'd need some extra guard code.

Upvotes: 95

freakydinde
freakydinde

Reputation: 1130

as Robert Groves said, Select-Object -First Occurence do the tricks, you can also use -Last Occurence.

by the way, like any other static .Net method you can use linq in powershell.

[Linq.Enumerable]::First($list)

[Linq.Enumerable]::Distinct($list)

[Linq.Enumerable]::Where($list, [Func[int,bool]]{ param($item) $item -gt 1 })

Upvotes: 8

Travis Parks
Travis Parks

Reputation: 8695

This is a really simple implementation for First:

function First($collection)
{
    foreach ($item in $collection)
    {
        return $item
    }
    return $null
}

Instead of returning $null, you could throw an InvalidOperationException exception.

Upvotes: 0

James
James

Reputation: 1419

Doug Finke produced a great video ( only 7 mins ) about converting C# to Powershell http://dougfinke.com/video/CSharpToPowerShell.html

Roberts example is very good indeed, though comma delimiting will implicitly be treated as an array

the shortest way of doing it would be to put it all into a single pipeline :

$dir = "App_Data", "bin", "Content" | % { if("drwxr-xr-x 1 ftp ftp              0 Mar 18 22:41 App_Data".EndsWith($_)) { $_ } } | select -first 1

Upvotes: 1

Related Questions