После создания следующего массива хеш-таблиц в PowerShell (версия 2):

$array = @()
$array += @{a = 1; b = 5}
$array += @{a = 3; b = 4}
$array += @{a = 5; b = 9}
$array += @{a = 7; b = 2}

Все следующие вызовы Sort-Object возвращают одну и ту же последовательность {a, b}: {5,9}, {7,2}, {1,5}, {3,4}:

$array | Sort-Object
$array | Sort-Object -Descending
$array | Sort-Object a
$array | Sort-Object b
$array | Sort-Object "a"
$array | Sort-Object -Property a
$array.GetEnumerator() | Sort-Object
$array.GetEnumerator() | Sort-Object a

Если $array вызывается напрямую, он возвращает объекты в том порядке, в котором они были введены, поэтому сортировка меняет порядок. Но, возможно, у него нет компаратора, поэтому он просто рассматривает каждый объект как равный ??

Цель состоит в том, чтобы отсортировать все объекты. Меня устраивают обходные пути, которые включают альтернативный настраиваемый объект, альтернативную коллекцию и / или альтернативную процедуру сортировки.

Изменить: чтобы прояснить, чего я пытаюсь достичь, это будет грубый эквивалент в С #

class MyClass {
    public int a;
    public int b;
}

// somewhere inside a method:
var objects = new List<MyClass>();
// code here to populate objects with some MyClass instances.
var sorted = objects.OrderBy(x => x.a);
12
Hutch 4 Май 2016 в 20:13

2 ответа

Лучший ответ

Sort-Object a не работает, потому что a не является свойством, это ключ в хеш-таблице. Можно запутаться, потому что PowerShell скрывает это от вас, принимая $ht.a, даже если он фактически использует $ht["a"] за кулисами, но если вы запустите $array | Get-Member, вы можете подтвердить, что свойство {{X5} } не существует.

Обходной путь заключается в сортировке с использованием вычисляемых свойств, которые обращаются к ключам в хэш-таблице. Я использовал Select-Object, чтобы показать хэш-таблицы в таблице, чтобы было легче увидеть результаты. Пример:

$array = @()
$array += @{a = 7; b = 2}
$array += @{a = 3; b = 4}
$array += @{a = 3; b = 1}
$array += @{a = 5; b = 9}
$array += @{a = 1; b = 5}

#No sort
$array | Select-Object @{n="a";e={$_.a}}, @{n="b";e={$_.b}}

a b
- -
7 2
3 4
3 1
5 9
1 5

#Sort by a asc, then b asc
$array | Sort-Object { $_.a },  { $_.b } | Select-Object @{n="a";e={$_.a}}, @{n="b";e={$_.b}}

a b
- -
1 5
3 1
3 4
5 9
7 2
11
Frode F. 4 Май 2016 в 17:59

См. Ответ @Frode F. для подробного объяснения, но в этом ответе отсутствует одна ситуация. Когда внешний контейнер имеет только один элемент (т.е. когда массив содержит только одну хеш-таблицу), Sort-Object «удобно» сортирует внутренний контейнер.

Так... Где $array.Count -eq 1, элементы этой хеш-таблицы сортируются. Где $array.Count -gt 1, элементы массива сортируются.

В качестве обходного пути используйте:

if ($array.Count -gt 1) {
    $result = Sort-Object { $_.a }, {$_.b }
} else {
    $result = $array
}    
2
Hutch 7 Июл 2017 в 20:46