【发布时间】:2016-02-04 20:15:51
【问题描述】:
当为我的“Split-ArrayInChunks”方法使用基于数组的脚本时,处理 190.000 多条记录需要很长时间,我的初始版本基于此代码(请参阅Split up an array into chunks and start a job on each one.)
$computers = gc c:\somedir\complist.txt
$n = 6
$complists = @{}
$count = 0
$computers |% {$complists[$count % $n] += @($_);$count++}
0..($n-1) |% {
start-job -scriptblock {gwmi win32_operatingsystem -computername $args} -argumentlist $complists[$_]
}
我找到了这篇文章Performance: The += Operator (and When to Avoid It),基本上推荐作者使用“System.Collections.Generic.List”或“System.Collections.ArrayList”来代替数组。所以我想出了这个实现:
function Split-ArrayInChunks_UsingGenericList($inArray, $numberOfChunks) {
$list = New-Object System.Collections.Generic.List[System.Collections.Generic.List[PSCustomObject]]
$count = 0
# populate with empty lists
0..($numberOfChunks-1) | % {
$list.Add((New-Object System.Collections.Generic.List[PSCustomObject]))
}
# create packages
$inArray | % {
$list[$count % $numberOfChunks].Add($_);
$count++
}
return $list.ToArray()
}
我也尝试使用“System.Collections.ArrayList”,但是这个函数返回一个平面数组。函数内部是 $arrayList 一个嵌套数组,但是一旦在函数外部,我就有一个平面数组(192169 个项目而不是 10 个块)。
function Split-ArrayInChunks_UsingArrayList($inArray, $numberOfChunks) {
$arryList = New-Object System.Collections.ArrayList
$count = 0
# populate
0..($numberOfChunks-1) | % {
$arryList.Add((New-Object System.Collections.ArrayList))
}
$inArray | % {
$arryList[$count % $numberOfChunks].Add($_);
$count++
}
Write-Host 'Number of arryList:'$arryList.Count
Write-Host 'Number of items in first arryList:' $arryList[0].Count
return $arryList
}
为了说明“扁平化”问题生成以下代码...
Write-Host '-------------------------------'
$packages1 = Split-ArrayInChunks_UsingGenericList $data.CrmRecords 10
Write-Host 'Number of packages1:'$packages1.Count
Write-Host 'Number of items in first package1:' $packages1[0].Count
Write-Host '-------------------------------'
$packages2 = Split-ArrayInChunks_UsingArrayList $data.CrmRecords 10
Write-Host 'Number of packages2:'$packages2.Count
Write-Host 'Number of items in first package2:' $packages2[0].Count
...这个输出:
-------------------------------
Number of packages1: 10
Number of items in first package1: 19215
-------------------------------
Number of arryList: 10
Number of items in first arryList: 19215
Number of packages2: 192169
Number of items in first package2: 1
所以我有两个问题:
- 任何改进我的“Split-ArrayInChunks_UsingArrayList”版本的选项(例如更快、更易读)?
- 为什么“ArrayInChunks_UsingArrayList”的返回值是一个平面数组,函数里面%arrayList是一个嵌套数组?
2016 年 2 月 4 日更新: 我根据反馈更新了我的代码(使用 [void] 来防止输出污染)并且它可以工作。唯一奇怪的是,当我使用 |format-table 时,我的版本 (Split-ArrayInChunks_UsingArrayList) 再次打印为平面列表:
function Split-ArrayInChunks_UsingArrayList($inArray, $numberOfChunks) {
$arryList = New-Object System.Collections.ArrayList
$count = 0
# populate
0..($numberOfChunks-1) | % {
[void]$arryList.Add((New-Object System.Collections.ArrayList))
}
$inArray | % {
[void]$arryList[$count % $numberOfChunks].Add($_);
$count++
}
return $arryList
}
function Split-ArrayInChunks_CommunityVersion($inArray, $numberOfChunks) {
$Lists = @{}
$count = 0
# populate
0..($numberOfChunks-1) | % {
$Lists[$_] = New-Object System.Collections.ArrayList
}
$inArray | % {
[void]$Lists[$count % $numberOfChunks].Add($_);
$count++
}
return $Lists
}
当我执行这段代码时...
Write-Host 'CommunityVersion'
Write-Host '-------------------------------'
Split-ArrayInChunks_CommunityVersion $list 6 | Format-Table -AutoSize
Write-Host 'ArrayInChunks_UsingArrayList'
Write-Host '-------------------------------'
Split-ArrayInChunks_UsingArrayList $list 6 | Format-Table -AutoSize
...这是控制台中的输出:
CommunityVersion
-------------------------------
Name Value
---- -----
5 {denn, getan, verhaftet}
4 {haben, Böses, Morgens, war}
3 {verleumdet, etwas, eines, es}
2 {Josef K., er, er, er}
1 {musste, dass, wurde, sagte}
0 {Jemand, ohne, hätte, »Wie ein Hund!«}
ArrayInChunks_UsingArrayList
-------------------------------
Jemand
ohne
hätte
»Wie ein Hund!«
musste
dass
wurde
sagte
Josef K.
er
er
er
verleumdet
etwas
eines
es
haben
Böses
Morgens
war
denn
getan
verhaftet
我不明白为什么“ArrayInChunks_UsingArrayList”打印为列表,它是一个嵌套数组,就像“ArrayInChunks_CommunityVersion”一样。
【问题讨论】:
-
ArrayList.Add不是void。 -
如果您正在从文件中读取列表,为什么不直接使用 -ReadCount 呢?
-
@mjolinor:不确定你的意思。就我而言,我从一个网络服务中加载了这 190.000 多条记录。我需要将这些记录打包成块,以便在作业中处理这些块。
-
留下一个建议的答案。
标签: arrays performance powershell arraylist