Skip to content
Browse files

Merge pull request #528 from nervetattoo/collection-reduce

Implements Collection::reduce
  • Loading branch information...
2 parents b737338 + f583206 commit 2d5fd7f21ecfeb5c4cf472963fdd181e49125a18 @nateabele nateabele committed Jun 6, 2012
View
16 data/Collection.php
@@ -257,6 +257,22 @@ public function map($filter, array $options = array()) {
}
/**
+ * Reduce, or fold, a collection down to a single value
+ *
+ * Overridden to load any data that has not yet been loaded.
+ *
+ * @param callback $filter The filter to apply.
+ * @param mixed $initial Initial value
+ * @return mixed A single reduced value
+ */
+ public function reduce($filter, $initial = false) {
+ if (!$this->closed()) {
+ while ($this->next()) {}
+ }
+ return parent::reduce($filter);
+ }
+
+ /**
* Sorts the objects in the collection, useful in situations where
* you are already using the underlying datastore to sort results.
*
View
14 data/collection/RecordSet.php
@@ -273,6 +273,20 @@ public function find($filter, array $options = array()) {
}
/**
+ * Reduce, or fold, a collection down to a single value
+ *
+ * Overriden to load any data that has not yet been loaded.
+ *
+ * @param callback $filter The filter to apply.
+ * @param mixed $initial Initial value
+ * @return mixed A single reduced value
+ */
+ public function reduce($filter, $initial = false) {
+ $this->offsetGet(null);
+ return parent::reduce($filter, $initial);
+ }
+
+ /**
* Applies a callback to a copy of all data in the collection
* and returns the result.
*
View
17 tests/cases/data/CollectionTest.php
@@ -150,6 +150,23 @@ public function testMap() {
}
/**
+ * Tests `Collection::reduce`.
+ */
+ public function testReduce() {
+ $collection = new DocumentSet();
+ $collection->set(array(
+ 'title' => 'Lorem Ipsum',
+ 'key' => 'value',
+ 'foo' => 'bar'
+ ));
+ $result = $collection->reduce(function($memo, $value) {
+ return trim($memo . ' ' . $value);
+ }, '');
+ $expected = 'Lorem Ipsum value bar';
+ $this->assertEqual($expected, $result);
+ }
+
+ /**
* Tests `Collection::data`.
*/
public function testData() {
View
9 tests/cases/data/collection/RecordSetTest.php
@@ -443,6 +443,15 @@ public function testMap() {
$this->assertEqual($expected, $result->get('_data'));
}
+ public function testReduce() {
+ $filter = function($memo, $rec) {
+ return $memo + $rec->id;
+ };
+ $expected = 10;
+ $result = $this->_recordSet->reduce($filter, 0);
+ $this->assertEqual($expected, $result);
+ }
+
public function testRecordSet() {
$expected = array(
'post1' => array(
View
9 tests/cases/util/CollectionTest.php
@@ -152,6 +152,15 @@ public function testCollectionMapFilter() {
$this->assertEqual(array(2, 3, 4, 5, 6), $result);
}
+ public function testCollectionReduceFilter() {
+ $collection = new Collection(array('data' => array(1, 2, 3)));
+ $filter = function($memo, $item) { return $memo + $item; };
+ $result = $collection->reduce($filter, 0);
+
+ $this->assertEqual(6, $collection->reduce($filter, 0));
+ $this->assertEqual(7, $collection->reduce($filter, 1));
+ }
+
/**
* Tests the `ArrayAccess` interface implementation for manipulating values by direct offsets.
*
View
11 util/Collection.php
@@ -354,6 +354,17 @@ public function map($filter, array $options = array()) {
}
/**
+ * Reduce, or fold, a collection down to a single value
+ *
+ * @param callback $filter The filter to apply.
+ * @param mixed $initial Initial value
+ * @return mixed A single reduced value
+ */
+ public function reduce($filter, $initial = false) {
+ return array_reduce($this->_data, $filter, $initial);
+ }
+
+ /**
* Sorts the objects in the collection.
*
* @param callable $sorter The sorter for the data, can either be a sort function like

0 comments on commit 2d5fd7f

Please sign in to comment.
Something went wrong with that request. Please try again.