从 PowerShell 数组中删除重复值

如何从 PowerShell 数组中删除副本?

$a = @(1,2,3,4,5,5,6,7,8,9,0,0)
262784 次浏览

使用 Select-Object(其别名是 select)与 -Unique开关; 例如:

$a = @(1,2,3,4,5,5,6,7,8,9,0,0)
$a = $a | select -Unique

另一种选择是使用带有 < br > -Unique开关的 Sort-Object(其别名是 sort,但只在 Windows 上使用) ,它结合了排序和删除重复项:

$a | sort -unique

如果列表已排序,可以使用 独一无二 cmdlet:

 $a | Get-Unique
$a | sort -unique

这种方法不区分大小写,因此可以删除具有不同大小写的重复字符串。

$ServerList = @(
"FS3",
"HQ2",
"hq2"
) | sort -Unique


$ServerList

上述产出:

FS3
HQ2

如果你想要完全防弹,我的建议是:

@('Apples', 'Apples ', 'APPLES', 'Banana') |
Sort-Object -Property @{Expression={$_.Trim()}} -Unique

产出:

Apples
Banana

这将使用 Property参数首先选择字符串 Trim(),因此将删除额外的空格,然后只选择 -Unique值。

更多关于 Sort-Object的信息:

Get-Help Sort-Object -ShowWindow

无论你是使用从 Powershell 2.0到5.1的 SORT -UNIQUESELECT -UNIQUE还是 GET-UNIQUE,所有给出的例子都是单列数组。我还没有得到这个功能跨数组与多列到 移开重复行留下一个单一的出现行跨所述列,或开发一个替代脚本解决方案。相反,这些 cmdlet 只返回数组中出现单一匹配项为 ONCE 的行,并转储有重复匹配项的所有内容。通常情况下,我必须从 Excel 中的最终 CSV 输出中手动删除重复数据才能完成报告,但有时我想在删除重复数据后继续在 Powershell 使用上述数据。

使用我的方法,您可以完全删除重复的值,只留下数组中只有1个值的值。不清楚这是不是 OP 真正想要的,但是我无法在网上找到这个解决方案的例子,所以就在这里。

$array=@'
Bananna
Apple
Carrot
Pear
Apricot
Pear
Bananna
'@ -split '\r\n'


($array | Group-Object -NoElement | ?{$_.count -eq 1}).Name

这就是如何从具有两个或多个属性的数组中获得唯一性的方法。排序是至关重要的,也是使其正确工作的关键。否则你只能得到一个项目返回。

PowerShell 脚本:

$objects = @(
[PSCustomObject] @{ Message = "1"; MachineName = "1" }
[PSCustomObject] @{ Message = "2"; MachineName = "1" }
[PSCustomObject] @{ Message = "3"; MachineName = "1" }
[PSCustomObject] @{ Message = "4"; MachineName = "1" }
[PSCustomObject] @{ Message = "5"; MachineName = "1" }
[PSCustomObject] @{ Message = "1"; MachineName = "2" }
[PSCustomObject] @{ Message = "2"; MachineName = "2" }
[PSCustomObject] @{ Message = "3"; MachineName = "2" }
[PSCustomObject] @{ Message = "4"; MachineName = "2" }
[PSCustomObject] @{ Message = "5"; MachineName = "2" }
[PSCustomObject] @{ Message = "1"; MachineName = "1" }
[PSCustomObject] @{ Message = "2"; MachineName = "1" }
[PSCustomObject] @{ Message = "3"; MachineName = "1" }
[PSCustomObject] @{ Message = "4"; MachineName = "1" }
[PSCustomObject] @{ Message = "5"; MachineName = "1" }
[PSCustomObject] @{ Message = "1"; MachineName = "2" }
[PSCustomObject] @{ Message = "2"; MachineName = "2" }
[PSCustomObject] @{ Message = "3"; MachineName = "2" }
[PSCustomObject] @{ Message = "4"; MachineName = "2" }
[PSCustomObject] @{ Message = "5"; MachineName = "2" }
)


Write-Host "Sorted on both properties with -Unique" -ForegroundColor Yellow
$objects | Sort-Object -Property Message,MachineName -Unique | Out-Host


Write-Host "Sorted on just Message with -Unique" -ForegroundColor Yellow
$objects | Sort-Object -Property Message -Unique | Out-Host


Write-Host "Sorted on just MachineName with -Unique" -ForegroundColor Yellow
$objects | Sort-Object -Property MachineName -Unique | Out-Host

产出:

Sorted on both properties with -Unique


Message MachineName
------- -----------
1       1
1       2
2       1
2       2
3       1
3       2
4       1
4       2
5       1
5       2




Sorted on just Message with -Unique


Message MachineName
------- -----------
1       1
2       1
3       1
4       1
5       2




Sorted on just MachineName with -Unique


Message MachineName
------- -----------
1       1
3       2

来源: Https://powershell.org/forums/topic/need-to-unique-based-on-multiple-properties/

要从数组中获取唯一的项并保持它们的顺序,可以使用.NET HashSet:

$Array = @(1, 3, 1, 2)
$Set = New-Object -TypeName 'System.Collections.Generic.HashSet[int]' -ArgumentList (,[int[]]$Array)


# PS> $Set
# 1
# 3
# 2

最适合包含大写和小写项的字符串数组,在这种情况下,需要以不区分大小写的方式保留每个项的第一个匹配项:

$Array = @("B", "b", "a", "A")
$Set = New-Object -TypeName 'System.Collections.Generic.HashSet[string]' -ArgumentList ([string[]]$Array, [StringComparer]::OrdinalIgnoreCase)


# PS> $Set
# B
# a

与其他类型一样可以正常工作。

简化语法,兼容 PowerShell 5.1和更新版本:

$Array = @("B", "b", "a", "A")
$Set = [Collections.Generic.HashSet[string]]::new([string[]]$Array, [StringComparer]::OrdinalIgnoreCase)


$Array = @(1, 3, 1, 2)
$Set = [Collections.Generic.HashSet[int]]::new([int[]]$Array)

许多提供的答案给出了错误的结果。 select -Unqiue不区分大小写。 sort -Unique提供了排序后的结果,您可能希望按照原始顺序获得这些结果。

威尔给出了一个很好的答案,但它是有缺陷的,因为它丢弃了所有重复的结果,却忘了保留其中的一个。

这是我创建的一个版本,似乎工作得很完美。它返回唯一的结果并保留原来的排序顺序。

($properties | Group-Object -NoElement).Name | Get-Unique