powershell - 处理大型数组

我有几百万个item,我需要处理和分组。这个列表的大小总是不同的,它可能是350万项或1千万项。

我尝试使用一个线程来处理数组,方法是循环遍历列表,并且分配给一个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



}



时间:

如果你正在处理大数据,使用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:Test201961SO_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



快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优化这一点,或者使用强类型列表,但是,在数组中的处理数百万元素仍然需要时间。

至于你的代码:不需要先在变量中捕获数组项值,然后再用它来添加到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()

...