2015-01-16 5 views
2

У меня есть массив, содержащий даты. Дата имеет следующий вид: tt.mm.yyyy. Я знаю, как сортировать массив с Sort-Object, но сортировка занимает много времени. Я нашел другой способ сортировки массивов, но он работает не так, как ожидалось.Сортировка массива, содержащего множество дат, быстро

Мой прежний код для сортировки массива был таким.

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

Но, поскольку я раньше сиада: этот способ сортировки слишком медленный. Метод Sort() от System.Array кажется намного быстрее.

[Array]::Sort([array]$array) 

Этот код сортирует массив, содержащий строки, намного быстрее, чем Sort-Object. Есть ли способ изменить описанный выше метод сортировки, например метод Sort-Object?

ответ

3

Метод .NET будет работать для дат, если вы убедитесь, что массив имеет тип DateTime.

Значение вы должны использовать

[DateTime[]]$dateArray 

вместо

[Array]$dateArray 

при ее создании. Затем вы можете использовать

[Array]::Sort($dateArray) 

для выполнения сортировки это сам ...

+0

Спасибо за помощь. У меня есть еще одна проблема. Когда я хочу поставить [DateTime []] перед моим массивом, означает [DateTime []] $ array, а $ array содержит даты, выход - Montag, 1. Juni 2015 00:00:00. Нужно ли мне анализировать даты в этой форме? –

+0

Нет проблем. Я немного не уверен, что вы имеете в виду в отношении разбора. Объекты являются полными объектами DateTime, но правила синтаксического анализа, возможно, будут меняться в соответствии с вашей локалью. У вас возникли проблемы с обработкой дат (в строке) в объектах DateTime? – ojk

+0

Я имел в виду преобразование, когда я использовал слово parsing. Прошу прощения за мою ошибку. Действительно, у меня проблемы с оформлением дат. Формат - dd.mm.yyyy в нормальном массиве. Все элементы - это строки. И когда я хочу проанализировать их в датах, используя [DateTime []], это результат «Montag, 1. Juni 2015 00:00:00». –

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