Passed
Push — 1.x ( fc8e80...0e4e66 )
by Ulises Jeremias
04:33
created

Sort   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 136
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 16
dl 0
loc 136
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A arraySort() 0 13 2
A mergeSorted() 0 3 1
D mergeSort() 0 39 9
A arraySorted() 0 3 1
A heapSort() 0 10 2
A heapSorted() 0 3 1
1
<?php namespace Mbh\Collection\Traits\Functional;
2
3
/**
4
 * MBHFramework
5
 *
6
 * @link      https://github.com/MBHFramework/mbh-framework
7
 * @copyright Copyright (c) 2017 Ulises Jeremias Cornejo Fandos
8
 * @license   https://github.com/MBHFramework/mbh-framework/blob/master/LICENSE (MIT License)
9
 */
10
11
use Mbh\Collection\Interfaces\Collection as CollectionInterface;
12
use Mbh\Collection\FixedArray;
13
use Mbh\Collection\CallbackHeap;
14
use Traversable;
15
use SplFixedArray;
16
use SplStack;
17
use LimitIterator;
18
19
trait Sort
20
{
21
    /**
22
     * Fallback behaviour to use the builtin array sort functions
23
     *
24
     * @param callable $callback The callback for comparison
25
     * @return CollectionInterface
26
     */
27
    public function arraySort(callable $callback = null)
28
    {
29
        $array = $this->toArray();
30
31
        if ($callback) {
32
            usort($array, $callback);
33
        } else {
34
            sort($array);
35
        }
36
37
        $this->setSfa(SplFixedArray::fromArray($array));
38
39
        return $this;
40
    }
41
42
    /**
43
     * Sorts the collection
44
     *
45
     * @param callable $callback The callback for comparison
46
     * @return CollectionInterface
47
     */
48
    public function arraySorted(callable $callback = null)
49
    {
50
        return $this->copy()->arraySort($callback);
51
    }
52
53
    /**
54
     * Sort by applying a CallbackHeap and building a new heap
55
     * Can be efficient for sorting large stored objects.
56
     *
57
     * @param callable $callback The comparison callback
58
     * @return CollectionInterface
59
     */
60
    public function heapSort(callable $callback)
61
    {
62
        $h = new CallbackHeap($callback);
63
        foreach ($this as $elem) {
64
            $h->insert($elem);
65
        }
66
67
        $this->setSfa(SplFixedArray::fromArray($h->toArray()));
68
69
        return $this;
70
    }
71
72
    /**
73
     * Sort by applying a CallbackHeap and building a new heap
74
     * Can be efficient for sorting large stored objects.
75
     *
76
     * @param callable $callback The comparison callback
77
     * @return CollectionInterface
78
     */
79
    public function heapSorted(callable $callback)
80
    {
81
        return $this->copy()->heapSort($callback);
82
    }
83
84
    /**
85
     * Sorts the collection with mergeSort
86
     *
87
     * @param callable $callback The callback for comparison
88
     * @return CollectionInterface
89
     */
90
    public function mergeSorted(callable $callback = null)
91
    {
92
        return $this->copy()->mergeSort($callback);
93
    }
94
95
    /**
96
     * Perform a bottom-up, non-recursive, in-place mergesort.
97
     * Efficient for very-large objects, and written without recursion
98
     * since PHP isn't well optimized for large recursion stacks.
99
     *
100
     * @param callable $callback The callback for comparison
101
     * @return CollectionInterface
102
     */
103
    public function mergeSort(callable $callback)
104
    {
105
        $count = $this->count();
106
        $result = new SplFixedArray($count);
107
108
        for ($k = 1; $k < $count; $k = $k << 1) {
109
            for ($left = 0; ($left + $k) < $count; $left += $k << 1) {
110
                $right = $left + $k;
111
                $rend = min($right + $k, $count);
112
                $m = $left;
113
                $i = $left;
114
                $j = $right;
115
                while ($i < $right && $j < $rend) {
116
                    if ($callback($this[$i], $this[$j]) <= 0) {
117
                        $result[$m] = $this[$i];
118
                        $i++;
119
                    } else {
120
                        $result[$m] = $this[$j];
121
                        $j++;
122
                    }
123
                    $m++;
124
                }
125
                while ($i < $right) {
126
                    $result[$m] = $this[$i];
127
                    $i++;
128
                    $m++;
129
                }
130
                while ($j < $rend) {
131
                    $result[$m] = $this[$j];
132
                    $j++;
133
                    $m++;
134
                }
135
                for ($m = $left; $m < $rend; $m++) {
136
                    $this[$m] = $result[$m];
137
                }
138
            }
139
        }
140
141
        return $this;
142
    }
143
144
    abstract protected function __construct(Traversable $array);
145
146
    abstract public static function fromItems(Traversable $array);
147
148
    abstract public function copy();
149
150
    abstract public function count(): int;
151
152
    abstract protected function setSfa(Traversable $traversable);
153
154
    abstract public function toArray(): array;
155
}
156