How to Check if an Array Contains a Value in PowerShell

To check if an array contains a value in PowerShell, use the -contains operator. It returns True or False, and it ignores case:

$cities = 'Dallas', 'Austin', 'Houston', 'El Paso'

$cities -contains 'Austin'
$cities -contains 'Miami'

Output:

True
False
PowerShell -contains operator checking if an array contains a value
-contains in PowerShell 7

That covers the everyday case. Below, I’ll handle the variations people actually search for: case-sensitive checks, partial matches, “does not contain”, several values at once, the index of an item, and arrays of objects.

Every example uses the same $cities array and runs the same way in PowerShell 7.6 and Windows PowerShell 5.1.

Use -contains in an if statement

Because -contains returns a Boolean, it drops straight into an if:

if ($cities -contains 'Houston') {
    'Houston is in the list'
}

Output:

Houston is in the list

How do I check if an array does not contain a value?

Use -notcontains. This pattern is handy for adding an item only when it’s missing:

if ($cities -notcontains 'Miami') {
    'Miami is not in the list, adding it'
    $cities += 'Miami'
}
$cities -join ', '

Output:

Miami is not in the list, adding it
Dallas, Austin, Houston, El Paso, Miami

-in and -notin: the same check, flipped

-in does the same job with the value on the left. Many people find it reads more naturally:

'austin' -in $cities
'Miami' -notin $cities

Output:

True
True

Pick whichever reads better. -in shines inside Where-Object, for example Where-Object City -in $cities.

Case-sensitive and case-insensitive checks

PowerShell operators ignore case, but the .NET .Contains() method doesn’t. Mixing them up causes a lot of “it works on my machine” bugs:

'-contains  austin : ' + ($cities -contains 'austin')
'-ccontains austin : ' + ($cities -ccontains 'austin')
'.Contains  austin : ' + $cities.Contains('austin')
'.Contains  Austin : ' + $cities.Contains('Austin')

Output:

-contains  austin : True
-ccontains austin : False
.Contains  austin : False
.Contains  Austin : True
Case-insensitive -contains vs case-sensitive .Contains() on a PowerShell array
-contains vs -ccontains vs .Contains() in Windows PowerShell 5.1

Use -ccontains when you need a case-sensitive operator.

Check if an array contains part of a string

-contains only matches whole items. For part of a string, use -like with wildcards. On an array, it returns every item that matches:

$cities -like '*as*'
'---'
if ($cities -like '*paso*') { 'At least one city contains "paso"' }

Output:

Dallas
El Paso
---
At least one city contains "paso"
PowerShell -like on an array to find items that contain part of a string
Partial matches with -like in PowerShell 7

A non-empty result counts as $true in an if, so the second check works without -contains at all.

For patterns, use -match, which also filters the array:

$cities -match '^(Dal|Hou)'

Output:

Dallas
Houston

Check if an array contains all or any of several values

All values

Find the values that are missing. If nothing is missing, the array contains all of them:

$required = 'Austin', 'Dallas'
$missing  = $required | Where-Object { $_ -notin $cities }

if (-not $missing) { 'All required cities are in the list' }
else               { "Missing: $($missing -join ', ')" }

Output:

All required cities are in the list

Any value

Keep the values that are in the array and count them:

$wanted = 'Miami', 'Austin', 'Denver'
$found  = $wanted | Where-Object { $_ -in $cities }

"Found $(@($found).Count) of $($wanted.Count): $($found -join ', ')"

Output:

Found 1 of 3: Austin

Check if one array contains another

The “all values” check works as a subset test. Wrap it in a function if you use it often:

$texasShortList = 'Houston', 'Dallas'
$otherList      = 'Houston', 'Chicago'

function Test-Subset($Small, $Big) { -not ($Small | Where-Object { $_ -notin $Big }) }

Test-Subset $texasShortList $cities
Test-Subset $otherList $cities

Output:

True
False

Find the index of an item

.IndexOf() returns the position, or -1 when the item isn’t there. It’s case-sensitive, so use [array]::FindIndex() with a condition when case shouldn’t matter:

$cities.IndexOf('Houston')          # case-sensitive
$cities.IndexOf('houston')          # -1 means not found

# case-insensitive index
[array]::FindIndex([string[]]$cities, [Predicate[string]] { param($c) $c -eq 'houston' })

Output:

2
-1
2

Find the first match and return it

.Where() with the 'First' mode stops at the first match, which is faster on big arrays:

$cities.Where({ $_ -like '*o*' }, 'First')

# or with the pipeline
$cities | Where-Object { $_.Length -gt 6 } | Select-Object -First 1

Output:

Houston
Houston

Search an array with two conditions

Combine conditions with -and or -or inside Where-Object:

$cities | Where-Object { $_ -like '*a*' -and $_.Length -le 6 }

Output:

Dallas
Austin

Why does -contains return False for an array of objects?

With objects, -contains compares the whole object, not a property. Pull the property out first, and PowerShell collects it from every object for you:

$servers = @(
    [pscustomobject]@{ Name = 'WEB01'; City = 'Dallas' }
    [pscustomobject]@{ Name = 'SQL01'; City = 'Austin' }
)

$servers -contains 'SQL01'          # compares whole objects: False
$servers.Name -contains 'SQL01'     # compares the Name values: True

Output:

False
True

Numbers and strings are converted

PowerShell converts the value to the type of the array items before comparing, so these both match:

@(1, 2, 3) -contains '2'
@('10', '20') -contains 20

Output:

True
True

That’s convenient, but watch for it when you compare IDs that could be text in one list and numbers in another.

Faster lookups for large lists

-contains checks items one by one. If you test thousands of values against a big list, load it into a HashSet first:

$ids = 1..100000 | ForEach-Object { "ID-$_" }
$set = [System.Collections.Generic.HashSet[string]]::new([string[]]$ids, [System.StringComparer]::OrdinalIgnoreCase)

'-contains: {0,6:N1} ms' -f (Measure-Command { 1..200 | ForEach-Object { $null = $ids -contains 'id-99999' } }).TotalMilliseconds
'HashSet  : {0,6:N1} ms' -f (Measure-Command { 1..200 | ForEach-Object { $null = $set.Contains('id-99999') } }).TotalMilliseconds

Output:

-contains: 1,395.5 ms
HashSet  :   10.8 ms

The OrdinalIgnoreCase comparer keeps the lookups case-insensitive, like -contains. Microsoft covers every containment operator in about_Comparison_Operators.

Frequently Asked Questions

How do I check if a PowerShell array contains a value?

Use $array -contains 'value'. It returns True or False and ignores case.

Is -contains case-sensitive in PowerShell?

No. Use -ccontains for a case-sensitive check. The .NET .Contains() method is case-sensitive.

How do I check if an array contains part of a string?

Use -like with wildcards, for example $array -like '*text*'. It returns the matching items.

What is the difference between -contains and -in?

They do the same check. -contains puts the collection on the left, and -in puts the value on the left.

How do I find the index of an item in a PowerShell array?

Use $array.IndexOf('value'). It returns -1 when the item isn’t found and it’s case-sensitive.

Want more on arrays? Start here: