快速排序包含大量日期的数组

时间:2015-01-16 08:16:58

标签: powershell

我有一个包含日期的巨大数组。日期格式如下:tt.mm.yyyy。我知道如何使用Sort-Object对数组进行排序,但排序需要花费大量时间。我找到了另一种排序数组的方法,但它没有按预期工作。

我之前对数组进行排序的代码是这样的。

$data | Sort-Object { [System.DateTime]::ParseExact($_, "dd.MM.yyyy", $null) }

但正如我之前所说的那样:这种排序方式太慢了。来自Sort()的{​​{1}}方法似乎要快得多。

System.Array

此代码对包含字符串的数组进行排序,速度比[Array]::Sort([array]$array) 快得多。有没有办法改变上面的排序方法,如Sort-Object方法?

2 个答案:

答案 0 :(得分:3)

如果确保数组的类型为DateTime,则.NET方法将适用于日期。

意思是你应该使用

[DateTime[]]$dateArray

而不是

[Array]$dateArray

创建时。然后你可以使用

[Array]::Sort($dateArray)

自己进行排序......

答案 1 :(得分:1)

您的输入数据是日期字符串,其日期格式不允许在"日期"中排序。订购。您必须将字符串转换为实际日期

Get-Date $_
[DateTime]::ParseExact($_, "dd.MM.yyyy", $null)

或将字符串日期的格式更改为ISO格式,这允许按日期顺序排序。

'{2}-{1}-{0}' -f ($_ -split '.')
'{0}-{1}-{2}' -f $_.Substring(6,4), $_.Substring(3,2), $_.Substring(0,2)
$_ -replace '(\d+)\.(\d+).(\d+)', '$3-$2-$1'

在某些时候,您必须在创建数据或排序时执行其中一项转换。

我运行了一些测试每次转换的WRT性能,而使用Substring()方法的字符串转换似乎是最快的方式:

PS C:\> $dates = 1..10000 | % {
>>   $day   = Get-Random -Min 1 -Max 28
>>   $month = (Get-Random -Min 1 -Max 12
>>   $year  = Get-Random -Min 1900 -Max 2014
>>   '{0:d2}.{1:d2}.{2}' -f $day, $month, $year
>> }
>>
PS C:\> Measure-Command { $dates | sort {Get-Date $_} }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 520
Ticks             : 15200396
TotalDays         : 1,75930509259259E-05
TotalHours        : 0,000422233222222222
TotalMinutes      : 0,0253339933333333
TotalSeconds      : 1,5200396
TotalMilliseconds : 1520,0396

PS C:\> Measure-Command { $dates | sort {'{2}-{1}-{0}' -f ($_ -split '.')} }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 413
Ticks             : 4139027
TotalDays         : 4,79054050925926E-06
TotalHours        : 0,000114972972222222
TotalMinutes      : 0,00689837833333333
TotalSeconds      : 0,4139027
TotalMilliseconds : 413,9027

PS C:\> Measure-Command { $dates | sort {$_ -replace '(\d+)\.(\d+).(\d+)', '$3-$2-$1'} }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 348
Ticks             : 3488962
TotalDays         : 4,03815046296296E-06
TotalHours        : 9,69156111111111E-05
TotalMinutes      : 0,00581493666666667
TotalSeconds      : 0,3488962
TotalMilliseconds : 348,8962

PS C:\> Measure-Command { $dates | sort {[DateTime]::ParseExact($_, "dd.MM.yyyy", $null)} }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 340
Ticks             : 3408966
TotalDays         : 3,9455625E-06
TotalHours        : 9,46935E-05
TotalMinutes      : 0,00568161
TotalSeconds      : 0,3408966
TotalMilliseconds : 340,8966

PS C:\> Measure-Command { $dates | sort {'{0}-{1}-{2}' -f $_.Substring(6,4), $_.Substring(3,2), $_.Substring(0,2)} }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 292
Ticks             : 2926835
TotalDays         : 3,38754050925926E-06
TotalHours        : 8,13009722222222E-05
TotalMinutes      : 0,00487805833333333
TotalSeconds      : 0,2926835
TotalMilliseconds : 292,6835