Заметки о Windows и других программных продуктах Microsoft...

Как отсортировать массив в PowerShell

Как отсортировать массив в PowerShell

Довольно часто для хранения данных в PowerShell используются одномерные массивы вида ″ключ=значение″ (name=value). И наиболее распространенным типом массива этого вида являются hash-массивы (hashtables).

Напомню, что hash-массив представляет коллекцию пар ключ-значение, которые упорядочены по хэш-коду ключа. В PowerShell для создания hash-массивов существует упрощенный синтаксис. Для примера создадим массив и выведем его содержимое:

$array = @{a=1;b=2;c=3}

создание hash-массива

 

Как видно из примера, содержимое hash-массива выдается не совсем в том порядке, в котором оно было добавлено. Попробуем изменить порядок, отсортировав вывод с помощью командлета Sort-Object:

$array | Sort-Object -Name

попытка отсортировать элементы массива

 

Однако номер не прошел и порядок остался прежним. Дело в том, что в данном случае массив передается как единый объект, соответственно командлету Sort-Object сортировать просто нечего. Исправить это можно с помощью метода GetEnumerator, который извлекает каждую строку массива как отдельный объект и передает ее по конвейеру. Например:

$array.GetEnumerator() | Sort-Object Name

Таким образом, с помощью GetEnumerator нам удалось отсортировать массив по имени. Для сортировки в обратном порядке можно использовать ключ Descending:

$array.GetEnumerator() | Sort-Object Name -Descending

сортировка массива с помощью метода GetEnumerator

 

В принципе вопрос решен, но ради интереса поместим получившийся массив в переменную $newarray и сравним его тип с исходным. Как видите, оба массива принадлежат пространству имен System.Collections, но исходный массив относится к классу Hashtable, а новый — к DictionaryEntry. О различиях между этими классами можно почитать здесь.

Примечание. Если быть точным, то DictionaryEntry является не классом, а структурой.

сравнение типов

 

Ну и раз уж речь зашла о классах, проверим, какие еще из них можно использовать для упорядочивания и сортировки массивов. Так класс SortedList представляет из себя коллекцию объектов, отсортированных по имени:

[System.Collections.SortedList]$array = @{a=1;b=2;c=3}

класс SortedList

 

Класс Stack  представляет неупорядоченную коллекцию объектов и работает по принципу стека, т.е. последним пришел — первым ушел:

[System.Collections.Stack]$array = @{a=1;b=2;c=3}

А класс Queue наоборот, работает по принципу очереди (первый пришел — первый ушел):

[System.Collections.Queue]$array = @{a=1;b=2;c=3}

классы Queue и Stack

 

И еще один класс OrderedDictionary, принадлежащий к пространству имен System.Collections.Specialized. Он также представляет из себя коллекцию пар ″ключ-значение″,  доступ к которым можно получить по ключу или по индексу. Если не вдаваться в подробности, то этот класс представляет из себя что-то вроде хэш-массива, элементы в котором упорядочены по индексу. Класс OrderedDictionary можно  использовать только с хэш-массивами. Он появился в PowerShell 3.0, и для его обозначения существует сокращенный синтаксис. Например:

$array = [ordered]@{a=1;b=2;c=3}

класс OrderedDictionary

 

Обратите внимание, что название класса ставится не перед именем переменной, а перед знаком @. При попытке указать для переменной данный тип будет выдана ошибка:

[ordered]$array = @{a=1;b=2;c=3}

ошибка при указании типа переменной

 

Такую же ошибку мы получим при попытке упорядочить уже созданный хэш-массив.

$array = @{a=1;b=2;c=3}
$newarray = [ordered]$array

ошибка при указании типа переменной

 

Таким образом, упорядочить массив можно только при его создании, сконвертировать готовый массив не получится. Впрочем при необходимости можно написать несложный скрипт для преобразования, а если лень — то  воспользоваться готовым.  Скрипт для конвертирования ConvertTo-OrderedDictionary можно найти в галерее Technet.

На этом все. Если вдруг тема статьи показалась интересной, то вот здесь можно узнать много нового о различных конструкциях для хранения данных (массивах, коллекциях и т.п.).

 
 
Комментарии

Пока нет комментариев.