Skip to content

Commit

Permalink
Update avg to work with generators and count after sort.
Browse files Browse the repository at this point in the history
  • Loading branch information
Iandenh committed Jul 19, 2017
1 parent 461eecd commit b31ce1c
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 27 deletions.
35 changes: 19 additions & 16 deletions src/Collection/CollectionTrait.php
Expand Up @@ -195,39 +195,42 @@ public function min($callback, $type = SORT_NUMERIC)
*/
public function avg($matcher = null)
{
$iterator = $this->unwrap();
$count = $iterator instanceof Countable ?
count($iterator) :
iterator_count($iterator);
$result = $this;
if ($matcher != null) {
$result = $result->extract($matcher);
}
$result = $result
->reduce(function ($acc, $current) {
list($count, $sum) = $acc;

return [$count + 1, $sum + $current];
}, [0, 0]);

if ($count === 0) {
if ($result[0] === 0) {
return null;
}

return $this->sumOf($matcher) / $count;
return $result[1] / $result[0];
}

/**
* {@inheritDoc}
*/
public function median($matcher = null)
{
$iterator = $this->unwrap();
$count = $iterator instanceof Countable ?
count($iterator) :
iterator_count($iterator);

if ($count === 0) {
return null;
}

$middle = (int)($count / 2);
$elements = $this;
if ($matcher != null) {
$elements = $elements->extract($matcher);
}
$values = $elements->toList();
sort($values);
$count = count($values);

if ($count === 0) {
return null;
}

$middle = (int)($count / 2);

if ($count % 2) {
return $values[$middle];
Expand Down
103 changes: 92 additions & 11 deletions tests/TestCase/Collection/CollectionTest.php
Expand Up @@ -60,13 +60,28 @@ public function testArrayIsWrapped()
}

/**
* Tests that it is possible to convert an array into a collection
* Provider for average tests
*
* @return void
* @return array
*/
public function testAvg()
public function avgProvider()
{
$items = [1, 2, 3];

return [
'array' => [$items],
'iterator' => [$this->yieldItems($items)]
];
}

/**
* ests the avg method
*
* @dataProvider avgProvider
* @return void
*/
public function testAvg($items)
{
$collection = new Collection($items);
$this->assertEquals(2, $collection->avg());

Expand All @@ -76,32 +91,84 @@ public function testAvg()
$items = [['foo' => 1], ['foo' => 2], ['foo' => 3]];
$collection = new Collection($items);
$this->assertEquals(2, $collection->avg('foo'));
$items = [
['invoice' => ['total' => 100]],
['invoice' => ['total' => 200]]
];
}

$this->assertEquals(150, (new Collection($items))->avg('invoice.total'));
/**
* Provider for average tests with use of a matcher
*
* @return array
*/
public function avgWithMatcherProvider()
{
$items = [['foo' => 1], ['foo' => 2], ['foo' => 3]];

return [
'array' => [$items],
'iterator' => [$this->yieldItems($items)]
];
}

/**
* Tests that it is possible to convert an array into a collection
* ests the avg method
*
* @dataProvider avgWithMatcherProvider
* @return void
*/
public function testMedian()
public function testAvgWithMatcher($items)
{
$collection = new Collection($items);
$this->assertEquals(2, $collection->avg('foo'));
}

/**
* Provider for some median tests
*
* @return array
*/
public function medianProvider()
{
$items = [5, 2, 4];

return [
'array' => [$items],
'iterator' => [$this->yieldItems($items)]
];
}

/**
* Tests the median method
*
* @dataProvider medianProvider
* @return void
*/
public function testMedian($items)
{
$collection = new Collection($items);
$this->assertEquals(4, $collection->median());

$collection = new Collection([]);
$this->assertNull($collection->median());
}

$items = [1, 2, 3, 4];
/**
* Tests the median method
*
* @dataProvider simpleProvider
* @return void
*/
public function testMedianEven($items)
{
$collection = new Collection($items);
$this->assertEquals(2.5, $collection->median());
}

/**
* Provider for median tests with use of a matcher
*
* @return array
*/
public function medianWithMatcherProvider()
{
$items = [
['invoice' => ['total' => 400]],
['invoice' => ['total' => 500]],
Expand All @@ -110,6 +177,20 @@ public function testMedian()
['invoice' => ['total' => 333]]
];

return [
'array' => [$items],
'iterator' => [$this->yieldItems($items)]
];
}

/**
* Tests the median method
*
* @dataProvider medianWithMatcherProvider
* @return void
*/
public function testMedianWithMatcher($items)
{
$this->assertEquals(333, (new Collection($items))->median('invoice.total'));
}

Expand Down

0 comments on commit b31ce1c

Please sign in to comment.