Select-对象-唯一
Select-Object -Unique
我的理解是
$list = @('1', '2', '3', '1', '4')
Select-Object -InputObject $list -Unique
应该return一个只有 4 个元素的数组,跳过第二个不唯一的“1”。
但我正在取回所有 5 个元素。我理解错了吗,或者 Select-Object 有错误,至少在我正在测试的 PS 5.1 中是这样?
只有少数例外,特别是 ConvertFrom-Csv
、Get-Random
、Join-String
和 Get-Member
, -InputObject
参数应被视为实现细节,其目的是促进管道输入,因此 不应 直接使用 。 built-in cmdlet 属于以下类别之一:
类别 A:select 几个 cmdlet,例如 Get-Member
有用 区分在将输入 collection 作为 参数 传递给 -InputObject
和隐式枚举 collection 的 元素 之间通过管道。
类别 B:select 几个 cmdlet,例如 ConvertFrom-Csv
(但 不是 ConvertTo-Csv
)、Get-Random
、Join-String
和 Out-String
,或者具有 array 值的 -InputObject
参数(例如-InputObject <psobject[]>
) 或 对传递给其 标量 InputObject
参数的参数显式执行枚举(例如,-InputObject <psobject>
).
- 对于 flat 输入 collections(这是典型的)[1],这样的 cmdlet 有效地处理直接 argument-passing 与管道输入相同 - 除了直接 argument-passing 是 快得多 ;见下文。
类别 C:不幸的是,大多数 cmdlet 都有标量 -InputObject
参数 和 进程collections作为一个整体传递给-InputObject
,这有效地使参数直接argument-passing无用。
这有点不幸,因为传递了一个已经in-memorycollectionas一个 cmdlet 的参数 比通过管道一个一个地发送它的元素要快得多 .
例如,比较使用直接 argument-passing 或管道将 100 万个项目传递给 Get-Random
的运行时间:Get-Random -InputObject (1..1e6)
与
1..1e6 | Get-Random
请注意,此优化有时也可用于 other cmdlet 参数;值得注意的是,您可以将 collection 传递给 Set-Content
的 -Value
参数,作为管道传递的替代方法,这大大加快了写入速度。
这是 built-in cmdlet 的分类和字母排序列表:
类别 A:管道输入和显式输入之间的有用区别 -InputObject
使用:处理 collections 作为一个整体 ,通过他们 -InputObject
;要一一处理它们的元素,请使用管道:
Add-Member
Export-Clixml
Get-Member
Trace-Command
类别 B:flat 的有用等价物 collections:您可以将 flat collections 直接传递给 -InputObject
加快处理速度:
ConvertFrom-Csv
Format-Custom
Format-List
Format-Table
Format-Wide
Get-Random
Join-String
Out-Host
Out-String
类别 C:无用区别:直接 -InputObject
使用毫无意义:
ConvertTo-Csv
ConvertTo-Html
ConvertTo-Xml
Export-Csv
ForEach-Object
Format-Hex
Get-Unique
Group-Object
Invoke-Command
Measure-Command
Measure-Object
Select-Object
Select-String
Sort-Object
Start-Job
Update-List
Where-Object
[1] nested collection 管道输入和 -InputObject
use 之间的处理差异:
那些枚举其 -InputObject
参数的 cmdlet 仅对输入 collection 执行 一个 枚举级别,并保留 嵌套 collections as-is.
相比之下,管道的使用可以导致 两个 级迭代,如以下 Join-String
示例所示:
PS> Join-String -InputObject ('foo', ('bar', 'baz'))
foobar baz
foo
和嵌套数组的字符串化 作为一个整体 - bar baz
- 加入了。
PS> 'foo', ('bar', 'baz') | Join-String
foobarbaz
foo
和嵌套数组的 枚举元素 已连接。
原因是在这种情况下发生 两次 处理传递,这是由于管道的枚举行为:首先传递 foo
,然后传递嵌套数组 'bar', 'baz'
,并且 single-level 枚举在 each 上执行,所有输入 objects 的结果被合并。
我的理解是
$list = @('1', '2', '3', '1', '4')
Select-Object -InputObject $list -Unique
应该return一个只有 4 个元素的数组,跳过第二个不唯一的“1”。
但我正在取回所有 5 个元素。我理解错了吗,或者 Select-Object 有错误,至少在我正在测试的 PS 5.1 中是这样?
只有少数例外,特别是
ConvertFrom-Csv
、Get-Random
、Join-String
和Get-Member
,-InputObject
参数应被视为实现细节,其目的是促进管道输入,因此 不应 直接使用 。 built-in cmdlet 属于以下类别之一:类别 A:select 几个 cmdlet,例如
Get-Member
有用 区分在将输入 collection 作为 参数 传递给-InputObject
和隐式枚举 collection 的 元素 之间通过管道。类别 B:select 几个 cmdlet,例如
ConvertFrom-Csv
(但 不是ConvertTo-Csv
)、Get-Random
、Join-String
和Out-String
,或者具有 array 值的-InputObject
参数(例如-InputObject <psobject[]>
) 或 对传递给其 标量InputObject
参数的参数显式执行枚举(例如,-InputObject <psobject>
).- 对于 flat 输入 collections(这是典型的)[1],这样的 cmdlet 有效地处理直接 argument-passing 与管道输入相同 - 除了直接 argument-passing 是 快得多 ;见下文。
类别 C:不幸的是,大多数 cmdlet 都有标量
-InputObject
参数 和 进程collections作为一个整体传递给-InputObject
,这有效地使参数直接argument-passing无用。
这有点不幸,因为传递了一个已经in-memorycollectionas一个 cmdlet 的参数 比通过管道一个一个地发送它的元素要快得多 .
例如,比较使用直接 argument-passing 或管道将 100 万个项目传递给
Get-Random
的运行时间:Get-Random -InputObject (1..1e6)
与
1..1e6 | Get-Random
请注意,此优化有时也可用于 other cmdlet 参数;值得注意的是,您可以将 collection 传递给
Set-Content
的-Value
参数,作为管道传递的替代方法,这大大加快了写入速度。
这是 built-in cmdlet 的分类和字母排序列表:
类别 A:管道输入和显式输入之间的有用区别
-InputObject
使用:处理 collections 作为一个整体 ,通过他们-InputObject
;要一一处理它们的元素,请使用管道:Add-Member
Export-Clixml
Get-Member
Trace-Command
类别 B:flat 的有用等价物 collections:您可以将 flat collections 直接传递给
-InputObject
加快处理速度:ConvertFrom-Csv
Format-Custom
Format-List
Format-Table
Format-Wide
Get-Random
Join-String
Out-Host
Out-String
类别 C:无用区别:直接
-InputObject
使用毫无意义:ConvertTo-Csv
ConvertTo-Html
ConvertTo-Xml
Export-Csv
ForEach-Object
Format-Hex
Get-Unique
Group-Object
Invoke-Command
Measure-Command
Measure-Object
Select-Object
Select-String
Sort-Object
Start-Job
Update-List
Where-Object
[1] nested collection 管道输入和 -InputObject
use 之间的处理差异:
那些枚举其 -InputObject
参数的 cmdlet 仅对输入 collection 执行 一个 枚举级别,并保留 嵌套 collections as-is.
相比之下,管道的使用可以导致 两个 级迭代,如以下 Join-String
示例所示:
PS> Join-String -InputObject ('foo', ('bar', 'baz'))
foobar baz
foo
和嵌套数组的字符串化 作为一个整体 - bar baz
- 加入了。
PS> 'foo', ('bar', 'baz') | Join-String
foobarbaz
foo
和嵌套数组的 枚举元素 已连接。
原因是在这种情况下发生 两次 处理传递,这是由于管道的枚举行为:首先传递 foo
,然后传递嵌套数组 'bar', 'baz'
,并且 single-level 枚举在 each 上执行,所有输入 objects 的结果被合并。