Why are you looping instead of just getting the active items and returning it? Look below, I have added a few other possible usages.
LIST ALL INSTALLED FEATURES - using Get-SPFeature
(Feature Alphabetically)
Get-SPFeature | Sort -Property DisplayName
(Feature ID)
Get-SPFeature | Sort -Property Id
(Alphabetically with Scope)
Get-SPFeature | Sort -Property Scope,DisplayName | FT -GroupBy Scope DisplayName,Id
(Export for Excel or such)
Get-SPFeature | Sort -Property Scope,DisplayName | FT -GroupBy Scope DisplayName,Id > c:\PATH\TO\WHATEVER.txt
(Activated Scoped Features - useful for hidden features)
Get-SPFeature -Site http://sitecollectionurl | Sort DisplayName | FT DisplayName,Id
(Web Scoped Features)
Get-SPSite http://SC-URL | Get-SPWeb -Limit ALL | %{ Get-SPFeature -Web $_ } | Sort DisplayName -Unique | FT DisplayName,Id
If you are parsing so you can figure out which items are active so you don't initiate an activate attempt, you are better off looking for what is NOT active and then initiate what you want. Just a suggestion, see code below.
Additional code for detecting inactive features:
$siteFeatures = Get-SPFeature | Where-Object {$_.Scope -eq "Site" } # Farm, WebApp, Site and Web
if ($siteFeatures -ne $null)
{
foreach ($feature in $siteFeatures)
{
# -Site can be replace by -Farm (without url), -WebApp, -Web
if ((Get-SPFeature -Site "http://URL/" | Where-Object {$_.Id -eq $feature.id}) -eq $null)
{
# Inactive feature
Write-Host "$($feature.Scope) feature $($feature.DisplayName) " -ForeGroundColor Red
}
}
}