Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implemented Collection::combine()

  • Loading branch information...
commit 4de65e7dc2d4041d37b381a90045f5c0045d5a62 1 parent b2e093a
@lorenzo lorenzo authored
View
74 src/Collection/CollectionTrait.php
@@ -628,6 +628,80 @@ public function append($items) {
}
/**
+ * Returrns a new collection where the values extracted based on a value path
+ * and then indexed by a key path. Optionally this method can produce parent
+ * groups absed on a group property path.
+ *
+ * ### Examples:
+ *
+ * {{{
+ * $items = [
+ * ['id' => 1, 'name' => 'foo', 'parent' => 'a'],
+ * ['id' => 2, 'name' => 'bar', 'parent' => 'b'],
+ * ['id' => 3, 'name' => 'baz', 'parent' => 'a'],
+ * ];
+ *
+ * $combined = (new Collection($items))->combine('id', 'name');
+ *
+ * //Result will look like this when converted to array
+ * [
+ * 1 => 'foo',
+ * 2 => 'bar',
+ * 3 => 'baz,
+ * ];
+ *
+ * $combined = (new Collection($items))->combine('id', 'name', 'parent');
+ *
+ * //Result will look like this when converted to array
+ * [
+ * 'a' => [1 => 'foo', 3 => 'baz'],
+ * 'b' => [2 => 'bar']
+ * ];
+ * }}}
+ *
+ * @param callable|string $keyPath the column name path to use for indexing
+ * or a function returning the indexing key out of the provided element
+ * @param callable|string $valuePath the column name path to use as the array value
+ * or a function returning the value out of the provided element
+ * @param callable|string $valuePath the column name path to use as the parent
+ * grouping key or a function returning the key out of the provided element
+ * @return \Cake\Collection\Collection
+ */
+ public function combine($keyPath, $valuePath, $groupPath = null) {
+ $options = [
+ 'keyPath' => $this->_propertyExtractor($keyPath),
+ 'valuePath' => $this->_propertyExtractor($valuePath),
+ 'groupPath' => $groupPath ? $this->_propertyExtractor($groupPath) : null
+ ];
+
+ $mapper = function($value, $key, $mapReduce) use ($options) {
+ $rowKey = $options['keyPath'];
+ $rowVal = $options['valuePath'];
+
+ if (!($options['groupPath'])) {
+ $mapReduce->emit($rowVal($value, $key), $rowKey($value, $key));
+ return;
+ }
+
+ $key = $options['groupPath']($value, $key);
+ $mapReduce->emitIntermediate(
+ [$rowKey($value, $key) => $rowVal($value, $key)],
+ $key
+ );
+ };
+
+ $reducer = function($values, $key, $mapReduce) {
+ $result = [];
+ foreach ($values as $value) {
+ $result += $value;
+ }
+ $mapReduce->emit($result, $key);
+ };
+
+ return new Collection(new MapReduce($this, $mapper, $reducer));
+ }
+
+/**
* Returns an array representation of the results
*
* @param boolean $preserveKeys whether to use the keys returned by this
View
45 tests/TestCase/Collection/CollectionTest.php
@@ -631,4 +631,49 @@ public function testCompile() {
$this->assertEquals(['a' => 4, 'b' => 5, 'c' => 6], $compiled->toArray());
}
+/**
+ * Tests the combine method
+ *
+ * @return void
+ */
+ public function testCombine() {
+ $items = [
+ ['id' => 1, 'name' => 'foo', 'parent' => 'a'],
+ ['id' => 2, 'name' => 'bar', 'parent' => 'b'],
+ ['id' => 3, 'name' => 'baz', 'parent' => 'a']
+ ];
+ $collection = (new Collection($items))->combine('id', 'name');
+ $expected = [1 => 'foo', 2 => 'bar', 3 => 'baz'];
+ $this->assertEquals($expected, $collection->toArray());
+
+ $expected = ['foo' => 1, 'bar' => 2, 'baz' => 3];
+ $collection = (new Collection($items))->combine('name', 'id');
+ $this->assertEquals($expected, $collection->toArray());
+
+ $collection = (new Collection($items))->combine('id', 'name', 'parent');
+ $expected = ['a' => [1 => 'foo', 3 => 'baz'], 'b' => [2 => 'bar']];
+ $this->assertEquals($expected, $collection->toArray());
+
+ $expected = [
+ '0-1' => ['foo-0-1' => '0-1-foo'],
+ '1-2' => ['bar-1-2' => '1-2-bar'],
+ '2-3' => ['baz-2-3' => '2-3-baz']
+ ];
+ $collection = (new Collection($items))->combine(
+ function($value, $key) {
+ return $value['name'] . '-' . $key;
+ },
+ function($value, $key) {
+ return $key . '-' . $value['name'];
+ },
+ function($value, $key) {
+ return $key . '-' . $value['id'];
+ }
+ );
+ $this->assertEquals($expected, $collection->toArray());
+
+ $collection = (new Collection($items))->combine('id', 'crazy');
+ $this->assertEquals([1 => null, 2 => null, 3 => null], $collection->toArray());
+ }
+
}
Please sign in to comment.
Something went wrong with that request. Please try again.