Skip to content

Commit

Permalink
Stabilize MetaSorter sorting (#430)
Browse files Browse the repository at this point in the history
* Use StableSort to create predictable MetaSorter results and stop generator loops

- `StableSort::uasort()` leveraged from https://github.com/vanderlee/PHP-stable-sort-functions under MIT license
  • Loading branch information
beryllium committed Apr 17, 2019
1 parent cb6624f commit 4ccb7ab
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 52 deletions.
102 changes: 51 additions & 51 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -15,6 +15,7 @@

use Sculpin\Contrib\ProxySourceCollection\Sorter\DefaultSorter;
use Sculpin\Contrib\ProxySourceCollection\Sorter\SorterInterface;
use StableSort\StableSort;

class ProxySourceCollection implements \ArrayAccess, \Iterator, \Countable
{
Expand Down Expand Up @@ -113,8 +114,33 @@ public function first()
return $this->items[$keys[0]];
}

/**
* Sorts proxy source items using the StableSort algorithm from Martijn van der Lee
*
* See: https://github.com/vanderlee/PHP-stable-sort-functions
*/
public function sort()
{
uasort($this->items, [$this->sorter, 'sort']);
$index = 0;
$comparator = [$this->sorter, 'sort'];

// add an index to provide stable sorting
foreach ($this->items as &$item) {
$item = [$index++, $item];
}
unset($item);

uasort($this->items, function ($a, $b) use ($comparator) {
$result = $comparator($a[1], $b[1]);

// use the index to prevent undefined behaviour when comparator reports items are "equal"
return $result === 0 ? $a[0] - $b[0] : $result;
});

// remove the index
foreach ($this->items as &$item) {
$item = $item[1];
}
unset($item);
}
}

0 comments on commit 4ccb7ab

Please sign in to comment.