Як впорядкувати масив в PowerShell.
Досить часто для зберігання даних в PowerShell використовуються одномірні масиви виду "ключ = значення" (name = value). І найбільш поширеним типом масиву цього виду є hash-масиви (hashtables).
Нагадаю, що hash-масив представляє колекцію пар ключ-значення, які впорядковані за хеш-коду ключа.У PowerShell для створення hash-масивів існує спрощений синтаксис. Для прикладу створимо масив і виведемо його вміст:
$ array = @ {a = 1; b = 2; c = 3}Як видно з прикладу, вміст hash-масиву видається не зовсім в тому порядку, в якому воно було додано. Спробуємо змінити порядок, відсортувавши висновок за допомогою командлета Sort-Object:
$ array | Sort-Object -Name
Однак номер не пройшов і порядок залишився колишнім.Справа в тому, що в даному випадку масив передається як єдиний об'єкт, відповідно Командлети Sort-Object сортувати просто нічого. Виправити це можна за допомогою методу GetEnumerator, який витягує кожен рядок масиву як окремий об'єкт і передає її по конвеєру. Наприклад:
$ array.GetEnumerator () | Sort-Object Name
Таким чином, за допомогою GetEnumerator нам вдалося впорядкувати масив на ім'я. Для сортування в зворотному порядку можна використовувати ключ Descending:
$ array.GetEnumerator () | Sort-Object Name -Descending
В принципі питання вирішене, але заради інтересу помістимо вийшов масив в змінну $ newarray і порівняємо його тип з вихідним.Як бачите, обидва масиви належать простору імен System.Collections, але вихідний масив відноситься до класу Hashtable, а новий - до DictionaryEntry. Про відмінності між цими класами можна почитати тут.
Примітка. Якщо бути точним, то DictionaryEntry є не класом, а структурою.
Ну і якщо вже мова зайшла про класи, перевіримо, які ще з них можна використовувати для впорядкування і сортування масивів.Так клас SortedList вдає із себе колекцію об'єктів, відсортованих по імені:
[System.Collections.SortedList] $ array = @ {a = 1; b = 2; c = 3}
Клас Stack представляє неупорядковану колекцію об'єктів і працює за принципом стека, тобто останнім прийшов - першим пішов:
[System.Collections.Stack] $ array = @ {a = 1; b = 2; c = 3}
А клас Queue навпаки, працює за принципом черги (перший прийшов - перший пішов):
[System.Collections.Queue] $ array = @ {a = 1; b = 2; c = 3}
І ще один клас OrderedDictionary, що належить до простору імен System.Collections.Specialized. Він також представляє з себе колекцію пар "ключ-значення", доступ до яких можна отримати по ключу або по індексу.Якщо не вдаватися в подробиці, то цей клас представляє з себе щось на зразок хеш-массива, елементи в якому впорядковані за індексом. Клас OrderedDictionary можна використовувати тільки з хеш-масивами. Він з'явився в PowerShell 3.0, і для його позначення існує скорочений синтаксис.Наприклад:
$ array = [ordered] @ {a = 1; b = 2; c = 3}
Зверніть увагу, що назва класу ставиться не перед ім'ям змінної, а перед знаком @. При спробі вказати для змінної даний тип буде видана помилка:
[ordered] $ array = @ {a = 1; b = 2; c = 3}
Такої ж помилки ми отримаємо при спробі впорядкувати вже створений хеш-масив.
$ array = @ {a = 1; b = 2; c = 3}
$ newarray = [ordered] $ array
Таким чином, упорядкувати масив можна тільки при його створенні, конвертувати готовий масив не вийде. Втім при необхідності можна написати нескладний скрипт для перетворення, а якщо лінь - то скористатися готовим.Скрипт для конвертації ConvertTo-OrderedDictionary можна знайти в галереї Technet.
На цьому все. Якщо раптом тема статті здалася цікавою, то ось тут можна дізнатися багато нового про різні конструкціях для зберігання даних (масивах, колекціях і т.п.).
.