在 PowerShell 中处理大型数组
Processing large arrays in PowerShell
我很难理解在 PowerShell 中处理大型 datasets/arrays 的最有效方法。我的数组包含数百万个需要处理和分组的项目。这个列表的大小总是不同的,这意味着它可能是 350 万个项目或 1000 万个项目。
示例:350 万个项目按“4”分组,如下所示:
项目 0,1,2,3 组合在一起 4,5,6,7 组合在一起等等。
我已经尝试使用单个线程处理数组,方法是循环遍历列表并分配给 pscustomobject,它只需要 45-50 多分钟即可完成。
我也曾尝试将数组分解成更小的数组,但这导致过程 运行 甚至更长。
$i=0
$d_array = @()
$item_array # Large dataset
While ($i -lt $item_array.length){
$o = "Test"
$oo = "Test"
$n = $item_array[$i];$i++
$id = $item_array[$i];$i++
$ir = $item_array[$i];$i++
$cs = $item_array[$i];$i++
$items = [PSCustomObject]@{
'field1' = $o
'field2' = $oo
'field3' = $n
'field4' = $id
'field5' = $ir
'field6'= $cs
}
$d_array += $items
}
我可以想象,如果我应用一个作业调度程序,允许我 运行 多个作业将大大减少处理时间,但我想让其他人采取快速有效的方式来解决这个问题。
这个怎么样?快 32.5 倍。用 += 制作数组会杀死小狗。它每次都复制整个数组。
$i=0
$item_array = 1..100000 # Large dataset
'measuring...'
# original 1 min 5 sec
# mine 2 sec
# other answer, 2 or 3 sec
# c# version 0.029 sec, 2241x faster!
measure-command {
$d_array =
While ($i -lt $item_array.length){
$o = "Test"
$oo = "Test"
$n = $item_array[$i];$i++
$id = $item_array[$i];$i++
$ir = $item_array[$i];$i++
$cs = $item_array[$i];$i++
# $items =
[PSCustomObject]@{
'field1' = $o
'field2' = $oo
'field3' = $n
'field4' = $id
'field5' = $ir
'field6'= $cs
}
# $d_array += $items
}
}
您可以使用 ArrayList, or perhaps even better by using a strongly typed List 对此进行一些优化,但遍历数组中的数百万个元素仍然需要时间..
至于您的代码:无需先捕获变量中的数组项值,然后再使用它添加到 PSCustomObject。
$item_array = 'a','b','c','d','e','f','g','h' # Large dataset
$result = New-Object System.Collections.Generic.List[PSCustomObject]
# or use an ArrayList: $result = New-Object System.Collections.ArrayList
$i = 0
While ($i -lt $item_array.Count) {
[void]$result.Add(
[PSCustomObject]@{
'field1' = "Test" # $o
'field2' = "Test" # $oo
'field3' = $item_array[$i++] #$n
'field4' = $item_array[$i++] #$id
'field5' = $item_array[$i++] #$ir
'field6' = $item_array[$i++] #$cs
}
)
}
# save to a CSV file maybe ?
$result | Export-Csv 'D:\blah.csv' -NoTypeInformation
如果需要结果再次变成'normal'数组,使用$result.ToArray()
如果您处理的是大数据,使用 C# 也很有效。
Add-Type -TypeDefinition @"
using System.Collections.Generic;
public static class Test
{
public static List<object> Convert(object[] src)
{
var result = new List<object>();
for(var i = 0; i <= src.Length - 4; i+=4)
{
result.Add( new {
field1 = "Test",
field2 = "Test",
field3 = src[i + 0],
field4 = src[i + 1],
field5 = src[i + 2],
field6 = src[i + 3]
});
}
return result;
}
}
"@
$item_array = 1..10000000
$result = [Test]::Convert($item_array)
虽然s version is unsurpassed, here my try with my local measurements from
同样$item_array = 1..100000
适用于所有版本
> .\SO_56406847.ps1
measuring...BDups
measuring...LotPings
measuring...Theo
measuring...js2010
measuring...rokumaru
BDups = 75,9949897 TotalSeconds
LotPings = 2,3663763 TotalSeconds
Theo = 2,4469917 TotalSeconds
js2010 = 2,9198114 TotalSeconds
rokumaru = 0,0109287 TotalSeconds
## Q:\Test19\SO_56406847.ps1
$i=0
$item_array = 1..100000 # Large dataset
'measuring...LotPings'
$LotPings = measure-command {
$d_array = for($i=0;$i -lt $item_array.length;$i+=4){
[PSCustomObject]@{
'field1' = "Test"
'field2' = "Test"
'field3' = $item_array[$i]
'field4' = $item_array[$i+1]
'field5' = $item_array[$i+2]
'field6' = $item_array[$i+3]
}
}
} # measure-command
我很难理解在 PowerShell 中处理大型 datasets/arrays 的最有效方法。我的数组包含数百万个需要处理和分组的项目。这个列表的大小总是不同的,这意味着它可能是 350 万个项目或 1000 万个项目。
示例:350 万个项目按“4”分组,如下所示:
项目 0,1,2,3 组合在一起 4,5,6,7 组合在一起等等。
我已经尝试使用单个线程处理数组,方法是循环遍历列表并分配给 pscustomobject,它只需要 45-50 多分钟即可完成。
我也曾尝试将数组分解成更小的数组,但这导致过程 运行 甚至更长。
$i=0
$d_array = @()
$item_array # Large dataset
While ($i -lt $item_array.length){
$o = "Test"
$oo = "Test"
$n = $item_array[$i];$i++
$id = $item_array[$i];$i++
$ir = $item_array[$i];$i++
$cs = $item_array[$i];$i++
$items = [PSCustomObject]@{
'field1' = $o
'field2' = $oo
'field3' = $n
'field4' = $id
'field5' = $ir
'field6'= $cs
}
$d_array += $items
}
我可以想象,如果我应用一个作业调度程序,允许我 运行 多个作业将大大减少处理时间,但我想让其他人采取快速有效的方式来解决这个问题。
这个怎么样?快 32.5 倍。用 += 制作数组会杀死小狗。它每次都复制整个数组。
$i=0
$item_array = 1..100000 # Large dataset
'measuring...'
# original 1 min 5 sec
# mine 2 sec
# other answer, 2 or 3 sec
# c# version 0.029 sec, 2241x faster!
measure-command {
$d_array =
While ($i -lt $item_array.length){
$o = "Test"
$oo = "Test"
$n = $item_array[$i];$i++
$id = $item_array[$i];$i++
$ir = $item_array[$i];$i++
$cs = $item_array[$i];$i++
# $items =
[PSCustomObject]@{
'field1' = $o
'field2' = $oo
'field3' = $n
'field4' = $id
'field5' = $ir
'field6'= $cs
}
# $d_array += $items
}
}
您可以使用 ArrayList, or perhaps even better by using a strongly typed List 对此进行一些优化,但遍历数组中的数百万个元素仍然需要时间..
至于您的代码:无需先捕获变量中的数组项值,然后再使用它添加到 PSCustomObject。
$item_array = 'a','b','c','d','e','f','g','h' # Large dataset
$result = New-Object System.Collections.Generic.List[PSCustomObject]
# or use an ArrayList: $result = New-Object System.Collections.ArrayList
$i = 0
While ($i -lt $item_array.Count) {
[void]$result.Add(
[PSCustomObject]@{
'field1' = "Test" # $o
'field2' = "Test" # $oo
'field3' = $item_array[$i++] #$n
'field4' = $item_array[$i++] #$id
'field5' = $item_array[$i++] #$ir
'field6' = $item_array[$i++] #$cs
}
)
}
# save to a CSV file maybe ?
$result | Export-Csv 'D:\blah.csv' -NoTypeInformation
如果需要结果再次变成'normal'数组,使用$result.ToArray()
如果您处理的是大数据,使用 C# 也很有效。
Add-Type -TypeDefinition @"
using System.Collections.Generic;
public static class Test
{
public static List<object> Convert(object[] src)
{
var result = new List<object>();
for(var i = 0; i <= src.Length - 4; i+=4)
{
result.Add( new {
field1 = "Test",
field2 = "Test",
field3 = src[i + 0],
field4 = src[i + 1],
field5 = src[i + 2],
field6 = src[i + 3]
});
}
return result;
}
}
"@
$item_array = 1..10000000
$result = [Test]::Convert($item_array)
虽然
同样$item_array = 1..100000
适用于所有版本
> .\SO_56406847.ps1
measuring...BDups
measuring...LotPings
measuring...Theo
measuring...js2010
measuring...rokumaru
BDups = 75,9949897 TotalSeconds
LotPings = 2,3663763 TotalSeconds
Theo = 2,4469917 TotalSeconds
js2010 = 2,9198114 TotalSeconds
rokumaru = 0,0109287 TotalSeconds
## Q:\Test19\SO_56406847.ps1
$i=0
$item_array = 1..100000 # Large dataset
'measuring...LotPings'
$LotPings = measure-command {
$d_array = for($i=0;$i -lt $item_array.length;$i+=4){
[PSCustomObject]@{
'field1' = "Test"
'field2' = "Test"
'field3' = $item_array[$i]
'field4' = $item_array[$i+1]
'field5' = $item_array[$i+2]
'field6' = $item_array[$i+3]
}
}
} # measure-command