powershell - 在 powershell 中切片数组(或列表)的更好方法
问题描述
如何在 CSV 文件中为每个用户导出 30 个用户的邮件地址。我已经尝试过了
$users = Get-ADUser -Filter * -Properties Mail
$nbCsv = [int][Math]::Ceiling($users.Count/30)
For($i=0; $i -le $nbCsv; $i++){
$arr=@()
For($j=(0*$i);$j -le ($i + 30);$j++){
$arr+=$users[$j]
}
$arr|Export-Csv -Path ($PSScriptRoot + "\ASSFAM" + ("{0:d2}" -f ([int]$i)) + ".csv") -Delimiter ";" -Encoding UTF8 -NoTypeInformation
}
它有效,但我认为有更好的方法来完成这项任务。你有什么想法吗?
谢谢你。
解决方案
如果你想要一个数组的子集,你可以使用..
范围运算符。数组的前 30 个元素是:
$users[0..29]
您也不必担心超出数组的末尾。如果有 100 个项目并且您正在调用$array[90..119]
,您将获得数组中的最后 10 个项目并且没有错误。您也可以在那里使用变量和表达式:
$users[$i..($i + 29)]
这是$i
th 值和 th 值之后的下 29$i
个值(如果它们存在)。
此外,在 PowerShell 中应该避免这种模式:
$array = @()
loop-construct {
$array += $value
}
数组在 .Net 中是不可变的,因此在 PowerShell 中是不可变的。这意味着向数组中添加元素+=
意味着“创建一个全新的数组,复制每个元素,然后将这个新项目放在上面,然后删除旧数组。” 它会产生巨大的内存压力,如果您正在处理超过几百个项目,它会明显变慢。
相反,只需这样做:
$array = loop-construct {
$value
}
字符串同样是不可变的,并且与+=
操作符有同样的问题。如果您需要通过连接构建字符串,则应使用 StringBuilder 类。
然而,最终,我会这样写:
$users = Get-ADUser -Filter * -Properties Mail
$exportFileTemplate = Join-Path -Path $PSScriptRoot -ChildPath 'ASSFAM{0:d2}.csv'
$batchSize = 30
$batchNum = 0
$row = 0
while ($row -lt $users.Count) {
$users[$row..($row + $batchSize - 1)] | Export-Csv ($exportFileTemplate -f $batchNum) -Encoding UTF8 -NoTypeInformation
$row += $batchSize
$batchNum++
}
$row
从技术上讲,并且$batchNum
可以滚动到一个变量中,但这更具可读性,IMO。
我相信你也可以用Select-Object
and来写这个Group-Object
,但与上面的相比,这将是相当复杂的,并且Group-Object
在 PowerShell 6 之前它的性能并不完全为人所知。
推荐阅读
- ruby-on-rails - 如何在rails中为用户设置默认头像?
- android - 我的 Android Studio 中出现这些错误,我什至无法启动该项目
- azure-cosmosdb - 使用 NoSQL 数据库存储值列表的最佳实践
- javascript - 为什么我的神经网络训练方法没有被调用?(ML5.JS)
- node.js - 跨多核 Node 的 PM2 进程管理器
- c++ - 你能解释一下运行时错误是如何解决的吗
- c++ - 传递二维数组的问题
- python - 在 Pandas 中探索 GROUPBY 和 JOIN 的捷径,无需创建中间数据帧
- python - pytorch RuntimeError: 标量类型 Double 的预期对象,但得到标量类型 Float
- algorithm - 用我的程序找到模数为 10^9+7 的几何序列的总和