NumericCollection::sum()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * Nozavroni/Collections
5
 * Just another collections library for PHP5.6+.
6
 *
7
 * @copyright Copyright (c) 2016 Luke Visinoni <[email protected]>
8
 * @author    Luke Visinoni <[email protected]>
9
 * @license   https://github.com/nozavroni/collections/blob/master/LICENSE The MIT License (MIT)
10
 */
11
namespace Noz\Collection;
12
13
use function Noz\is_traversable;
14
15
/**
16
 * Class NumericCollection.
17
 *
18
 * A collection that allows only numeric items, meaning only int, float, or numeric strings.
19
 *
20
 * @package Noz\Collection
21
 *
22
 * @todo $this->set('foo', 'bar'); should throw an exception because only
23
 *     numeric values are allowed. Either that or converted to int.
24
 */
25
class NumericCollection extends AbstractCollection
26
{
27
    /**
28
     * Increment an item.
29
     *
30
     * Increment the item specified by $key by one value. Intended for integers
31
     * but also works (using this term loosely) for letters. Any other data type
32
     * it may modify is unintended behavior at best.
33
     *
34
     * This method modifies its internal data array rather than returning a new
35
     * collection.
36
     *
37
     * @param mixed $key      The key of the item you want to increment.
38
     * @param int   $interval The interval that $key should be incremented by
39
     *
40
     * @return $this
41
     */
42
    public function increment($key, $interval = 1)
43
    {
44
        $val = $this->get($key, null, true);
45
        for ($i = 0; $i < $interval; $i++) {
46
            $val++;
47
        }
48
        $this->set($key, $val);
49
50
        return $this;
51
    }
52
53
    /**
54
     * Decrement an item.
55
     *
56
     * Frcrement the item specified by $key by one value. Intended for integers.
57
     * Does not work for letters and if it does anything to anything else, it's
58
     * unintended at best.
59
     *
60
     * This method modifies its internal data array rather than returning a new
61
     * collection.
62
     *
63
     * @param mixed $key      The key of the item you want to decrement.
64
     * @param int   $interval The interval that $key should be decremented by
65
     *
66
     * @return $this
67
     */
68
    public function decrement($key, $interval = 1)
69
    {
70
        $val = $this->get($key, null, true);
71
        for ($i = 0; $i < $interval; $i++) {
72
            $val--;
73
        }
74
        $this->set($key, $val);
75
76
        return $this;
77
    }
78
79
    /**
80
     * Get the sum.
81
     *
82
     * @return int|float The sum of all values in collection
83
     */
84
    public function sum()
85
    {
86
        return array_sum($this->toArray());
87
    }
88
89
    /**
90
     * Get the average.
91
     *
92
     * @return float|int The average value from the collection
93
     */
94
    public function average()
95
    {
96
        return $this->sum() / $this->count();
97
    }
98
99
    /**
100
     * Get the mode.
101
     *
102
     * @return float|int The mode
103
     */
104
    public function mode()
105
    {
106
        $counts = $this->counts()->toArray();
107
        arsort($counts);
108
        $mode = key($counts);
109
110
        return (strpos($mode, '.')) ? floatval($mode) : intval($mode);
111
    }
112
113
    /**
114
     * Get the median value.
115
     *
116
     * @return float|int The median value
117
     */
118
    public function median()
119
    {
120
        $count = $this->count();
121
        $data  = $this->toArray();
122
        natcasesort($data);
123
        $middle = $count / 2;
124
        $values = array_values($data);
125
        if ($count % 2 == 0) {
126
            // even number, use middle
127
            $low  = $values[$middle - 1];
128
            $high = $values[$middle];
129
130
            return ($low + $high) / 2;
131
        }
132
        // odd number return median
133
        return $values[$middle];
134
    }
135
136
    /**
137
     * Get the maximum value.
138
     *
139
     * @return mixed The maximum
140
     */
141
    public function max()
142
    {
143
        return max($this->data);
144
    }
145
146
    /**
147
     * Get the minimum value.
148
     *
149
     * @return mixed The minimum
150
     */
151
    public function min()
152
    {
153
        return min($this->data);
154
    }
155
156
    /**
157
     * Get the number of times each item occurs in the collection.
158
     *
159
     * This method will return a NumericCollection where keys are the
160
     * values and values are the number of times that value occurs in
161
     * the original collection.
162
     *
163
     * @return NumericCollection
164
     */
165
    public function counts()
166
    {
167
        return new self(array_count_values($this->toArray()));
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    protected function prepareData($data)
174
    {
175
        return $data;
176
    }
177
178
    protected function isConsistentDataStructure($data)
179
    {
180
        if (!is_traversable($data)) {
181
            return false;
182
        }
183
        foreach ($data as $val) {
184
            if (!is_numeric($val)) {
185
                return false;
186
            }
187
        }
188
189
        return true;
190
    }
191
}
192