Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

feat(orderBy): Stable sort the input array #12408

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/ng/filter/orderBy.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ function orderByFilter($parse) {
if (sortPredicate.length === 0) { sortPredicate = ['+']; }

var predicates = processPredicates(sortPredicate, reverseOrder);
// Add a predicate at the end that evaluates to the element index. This makes the
// sort stable as it works as a tie-breaker when all the input predicates cannot
// distinguish between two elements.
predicates.push({ get: function() { return {}; }, descending: reverseOrder ? -1 : 1});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should leave a comment explaining this, it won't be very nice to have to look up this issue in the blame for this function to figure out what this means once it stops being clear, otherwise this looks maybe a bit brittle

Just a quick header comment with an overview explaining how the predicate works, imho


// The next three lines are a version of a Swartzian Transform idiom from Perl
// (sometimes called the Decorate-Sort-Undecorate idiom)
Expand Down
29 changes: 29 additions & 0 deletions test/ng/filter/orderBySpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,35 @@ describe('Filter: orderBy', function() {
it('should sort mixed array of objects and values in a stable way', function() {
expect(orderBy([{foo: 2}, {foo: {}}, {foo: 3}, {foo: 4}], 'foo')).toEqualData([{foo: 2}, {foo: 3}, {foo: 4}, {foo: {}}]);
});


it('should perform a stable sort', function() {
expect(orderBy([
{foo: 2, bar: 1}, {foo: 1, bar: 2}, {foo: 2, bar: 3},
{foo: 2, bar: 4}, {foo: 1, bar: 5}, {foo: 2, bar: 6},
{foo: 2, bar: 7}, {foo: 1, bar: 8}, {foo: 2, bar: 9},
{foo: 1, bar: 10}, {foo: 2, bar: 11}, {foo: 1, bar: 12}
], 'foo'))
.toEqualData([
{foo: 1, bar: 2}, {foo: 1, bar: 5}, {foo: 1, bar: 8},
{foo: 1, bar: 10}, {foo: 1, bar: 12}, {foo: 2, bar: 1},
{foo: 2, bar: 3}, {foo: 2, bar: 4}, {foo: 2, bar: 6},
{foo: 2, bar: 7}, {foo: 2, bar: 9}, {foo: 2, bar: 11}
]);

expect(orderBy([
{foo: 2, bar: 1}, {foo: 1, bar: 2}, {foo: 2, bar: 3},
{foo: 2, bar: 4}, {foo: 1, bar: 5}, {foo: 2, bar: 6},
{foo: 2, bar: 7}, {foo: 1, bar: 8}, {foo: 2, bar: 9},
{foo: 1, bar: 10}, {foo: 2, bar: 11}, {foo: 1, bar: 12}
], 'foo', true))
.toEqualData([
{foo: 2, bar: 11}, {foo: 2, bar: 9}, {foo: 2, bar: 7},
{foo: 2, bar: 6}, {foo: 2, bar: 4}, {foo: 2, bar: 3},
{foo: 2, bar: 1}, {foo: 1, bar: 12}, {foo: 1, bar: 10},
{foo: 1, bar: 8}, {foo: 1, bar: 5}, {foo: 1, bar: 2}
]);
});
});


Expand Down