问题描述
我有一个包含在名为 $attendance
的变量中的 PSCustomObject 数组。
event name date present
----- ---- ---- -------
A01 Mika 2021-02-22 1
A01 John 2021-02-22 0
B03 Mika 2021-02-24 0
B03 John 2021-02-24 1
event name date present
----- ---- ---- -------
A01 Mika 2021-02-22 Yes
A01 John 2021-02-22 No
B03 Mika 2021-02-24 No
B03 John 2021-02-24 Yes
我可以使用 ForEach-Object
循环更改它,但这会遍历整个对象。
$attendance |
ForEach-Object {
if ($_.present -eq '1') { $_.present = 'Yes' } else {$_.present = 'No' }
}
为了缩短代码,我尝试了以下变体,但无法将其折叠回 $attendance
变量。
$attendance.present.replace('1','Yes').replace('0','No')
是否有使用点表示法更改 present
列值的单行或更简单的方法?
解决方法
另一种可能是在此使用 Select-Object
:
$attendance | Select-Object *,@{Name = 'present'; Expression = {('No','Yes')[[math]::Sign($_.present)]}} -ExcludeProperty present
输出:
event name date present
----- ---- ---- -------
A01 Mika 2021-02-22 Yes
A01 John 2021-02-22 No
B03 Mika 2021-02-24 No
B03 John 2021-02-24 Yes
,
我不知道如何在不使用循环的情况下更新所有值,但您可以缩短代码以
$attendance | % {$_.present = @('Yes','No')[$_.present -eq '0']}
另一种选择可能是添加自定义属性进行转换
$attendance |
Add-Member -Name 'yesno' -MemberType ScriptProperty -Value {
return @('Yes','No')[$this.present -eq '0']
}
示例 请注意,我的 csv 分隔符是逗号,因此请相应更改
$attendance = @'
event,name,date,present
A01,Mika,2021-02-22,1
A01,John,0
B03,2021-02-24,1
'@ | ConvertFrom-Csv
$attendance | Add-Member -Name 'yesno' -MemberType ScriptProperty -Value {return @('Yes','No')[$this.present -eq '0']}
$attendance | ft -a
event name date present yesno
----- ---- ---- ------- -----
A01 Mika 2021-02-22 1 Yes
A01 John 2021-02-22 0 No
B03 Mika 2021-02-24 0 No
B03 John 2021-02-24 1 Yes
,
不幸的是,使用像 $attendance.present
这样的点符号会创建一个新数组,该数组不能用于操作 PSCustomObject
的原始数组。
我能想到的最短时间:
$attendance.foreach({ $_.present = ('No','Yes')[ $_.present ] })
无论 present
是整数还是字符串,这都有效。当用于索引数组时,PowerShell 会自动将字符串转换为整数。
稍长,使用 ternary operator(需要 PS7+):
$attendance.foreach({ $_.present = $_.present -eq 0 ? 'No' : 'Yes' })
我更喜欢后者,因为我认为它更容易阅读。
,通过使用 Replace()
方法,您只是在操作存储在 present 中的字符串,它不会更新 $attendance
上的值,也没有字符串方法可以做到这一点。