Skip to content

Commit 0067dec

Browse files
authored
Fix Sort-Object -Stable -Unique to actually do stable sorting (PowerShell#17189)
1 parent ad5a6ff commit 0067dec

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

src/Microsoft.PowerShell.Commands.Utility/commands/utility/Sort-Object.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private int Heapify(List<OrderByPropertyEntry> dataToSort, OrderByPropertyCompar
147147

148148
// Tracking the index is necessary so that unsortable items can be output at the end, in the order
149149
// in which they were received.
150-
for (int dataIndex = 0, discardedDuplicates = 0; dataIndex < dataToSort.Count - discardedDuplicates; dataIndex++)
150+
for (int dataIndex = 0, discardedDuplicates = 0; dataIndex + discardedDuplicates < dataToSort.Count; dataIndex++)
151151
{
152152
// Min-heap: if the heap is full and the root item is larger than the entry, discard the entry
153153
// Max-heap: if the heap is full and the root item is smaller than the entry, discard the entry
@@ -157,20 +157,19 @@ private int Heapify(List<OrderByPropertyEntry> dataToSort, OrderByPropertyCompar
157157
}
158158

159159
// If we're doing a unique sort and the entry is not unique, discard the duplicate entry
160-
if (Unique && !uniqueSet.Add(dataToSort[dataIndex]))
160+
if (Unique && !uniqueSet.Add(dataToSort[dataIndex + discardedDuplicates]))
161161
{
162162
discardedDuplicates++;
163-
if (dataIndex != dataToSort.Count - discardedDuplicates)
164-
{
165-
// When discarding duplicates, replace them with an item at the end of the list and
166-
// adjust our counter so that we check the item we just swapped in next
167-
dataToSort[dataIndex] = dataToSort[dataToSort.Count - discardedDuplicates];
168-
dataIndex--;
169-
}
170-
163+
dataIndex--;
171164
continue;
172165
}
173166

167+
// Shift next non-duplicate entry into place
168+
if (discardedDuplicates > 0)
169+
{
170+
dataToSort[dataIndex] = dataToSort[dataIndex + discardedDuplicates];
171+
}
172+
174173
// Add the current item to the heap and bubble it up into the correct position
175174
int childIndex = dataIndex;
176175
while (childIndex > 0)

test/powershell/Modules/Microsoft.PowerShell.Utility/Sort-Object.Tests.ps1

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,18 @@ Describe 'Sort-Object Stable Unit Tests' -Tags 'CI' {
296296
$results[1] | Should -Be 1
297297
$results[2] | Should -Be 3
298298
}
299+
300+
It "Sort-Object with Unique Stable should return proper records"{
301+
$Record1=[PSCustomObject]@{Key="A";Record="A1"}
302+
$Record2=[PSCustomObject]@{Key="A";Record="A2"}
303+
$Record3=[PSCustomObject]@{Key="B";Record="B1"}
304+
$Record4=[PSCustomObject]@{Key="B";Record="B2"}
305+
$Records = @($Record1,$Record2,$Record3,$Record4)
306+
$results = $Records | Sort-Object -Stable -Unique -Property Key
307+
308+
$results[0] | Should -Be $Records[0]
309+
$results[1] | Should -Be $Records[2]
310+
}
299311
}
300312
}
301313

0 commit comments

Comments
 (0)