diff --git a/src/Set/Edges.php b/src/Set/Edges.php index 5d47ee83..dd90ac0a 100644 --- a/src/Set/Edges.php +++ b/src/Set/Edges.php @@ -237,7 +237,7 @@ public function getEdgesMatch($callbackCheck) * * Edge index positions will be left unchanged. * - * @param int $orderBy criterium to sort by. see self::ORDER_WEIGHT, etc. + * @param string|int $orderBy criterium to sort by. see edge attribute names or self::ORDER_WEIGHT, etc. * @param bool $desc whether to return biggest first (true) instead of smallest first (default:false) * @return Edges a new Edges set ordered by the given $orderBy criterium * @throws InvalidArgumentException if criterium is unknown @@ -291,7 +291,7 @@ public function getEdgesShuffled() /** * get first edge ordered by given criterium $orderBy * - * @param int $orderBy criterium to sort by. see self::ORDER_WEIGHT, etc. + * @param string|int $orderBy criterium to sort by. see edge attribute names or self::ORDER_WEIGHT, etc. * @param bool $desc whether to return biggest (true) instead of smallest (default:false) * @return Edge * @throws InvalidArgumentException if criterium is unknown @@ -464,7 +464,7 @@ private function getEdgeMatchOrNull($callbackCheck) /** * get callback/Closure to be called on Edge instances for given callback identifier * - * @param callable|int $callback + * @param callable|string|int $callback * @throws InvalidArgumentException * @return callable */ @@ -479,6 +479,12 @@ private function getCallback($callback) return $callback; } + if (is_string($callback)) { + return function (Edge $edge) use ($callback) { + return $edge->getAttribute($callback); + }; + } + static $methods = array( self::ORDER_WEIGHT => 'getWeight', self::ORDER_CAPACITY => 'getCapacity', diff --git a/src/Set/Vertices.php b/src/Set/Vertices.php index 41a8d6d8..3e1a583b 100644 --- a/src/Set/Vertices.php +++ b/src/Set/Vertices.php @@ -241,7 +241,7 @@ public function getVerticesMatch($callbackCheck) * Vertex index positions will be left unchanged, so if you call this method * on a VerticesMap, it will also return a VerticesMap. * - * @param int $orderBy criterium to sort by. see Vertex::ORDER_ID, etc. + * @param string|int $orderBy criterium to sort by. see vertex attribute names or Vertex::ORDER_ID, etc. * @param bool $desc whether to return biggest first (true) instead of smallest first (default:false) * @return Vertices a new Vertices set ordered by the given $orderBy criterium * @throws InvalidArgumentException if criterium is unknown @@ -329,7 +329,7 @@ public function getVerticesIntersection($otherVertices) /** * get first vertex (optionally ordered by given criterium $by) from given array of vertices * - * @param int $orderBy criterium to sort by. see Vertex::ORDER_ID, etc. + * @param string|int $orderBy criterium to sort by. see vertex attribute names or Vertex::ORDER_ID, etc. * @param bool $desc whether to return biggest (true) instead of smallest (default:false) * @return Vertex * @throws InvalidArgumentException if criterium is unknown @@ -510,7 +510,7 @@ private function getVertexMatchOrNull($callbackCheck) /** * get callback/Closure to be called on Vertex instances for given callback identifier * - * @param callable|int $callback + * @param callable|string|int $callback * @throws InvalidArgumentException * @return callable */ @@ -525,6 +525,12 @@ private function getCallback($callback) return $callback; } + if (is_string($callback)) { + return function (Vertex $vertex) use ($callback) { + return $vertex->getAttribute($callback); + }; + } + static $methods = array( self::ORDER_ID => 'getId', self::ORDER_GROUP => 'getGroup' diff --git a/src/Walk.php b/src/Walk.php index db7b644e..e29d19f1 100644 --- a/src/Walk.php +++ b/src/Walk.php @@ -43,13 +43,13 @@ public static function factoryFromEdges($edges, Vertex $startVertex) * create new walk instance between given set of Vertices / array of Vertex instances * * @param Vertices|Vertex[] $vertices - * @param int|null $by + * @param null|string|null $orderBy * @param bool $desc * @return Walk * @throws UnderflowException if no vertices were given * @see Edges::getEdgeOrder() for parameters $by and $desc */ - public static function factoryFromVertices($vertices, $by = null, $desc = false) + public static function factoryFromVertices($vertices, $orderBy = null, $desc = false) { $edges = array(); $last = NULL; @@ -58,10 +58,10 @@ public static function factoryFromVertices($vertices, $by = null, $desc = false) if ($last !== NULL) { // pick edge between last vertex and this vertex /* @var $last Vertex */ - if ($by === null) { + if ($orderBy === null) { $edges []= $last->getEdgesTo($vertex)->getEdgeFirst(); } else { - $edges []= $last->getEdgesTo($vertex)->getEdgeOrder($by, $desc); + $edges []= $last->getEdgesTo($vertex)->getEdgeOrder($orderBy, $desc); } } $last = $vertex; @@ -78,14 +78,14 @@ public static function factoryFromVertices($vertices, $by = null, $desc = false) * * @param Vertex[] $predecessors map of vid => predecessor vertex instance * @param Vertex $vertex start vertex to search predecessors from - * @param int|null $by + * @param null|string|int $orderBy * @param bool $desc * @return Walk * @throws UnderflowException * @see Edges::getEdgeOrder() for parameters $by and $desc * @uses self::factoryFromVertices() */ - public static function factoryCycleFromPredecessorMap(array $predecessors, Vertex $vertex, $by = null, $desc = false) + public static function factoryCycleFromPredecessorMap(array $predecessors, Vertex $vertex, $orderBy = null, $desc = false) { // find a vertex in the cycle $vid = $vertex->getId(); @@ -121,23 +121,23 @@ public static function factoryCycleFromPredecessorMap(array $predecessors, Verte // additional edge from last vertex to first vertex $vertices[] = reset($vertices); - return self::factoryCycleFromVertices($vertices, $by, $desc); + return self::factoryCycleFromVertices($vertices, $orderBy, $desc); } /** * create new cycle instance with edges between given vertices * * @param Vertex[]|Vertices $vertices - * @param int|null $by + * @param null|string|int $orderBy * @param bool $desc * @return Walk * @throws UnderflowException if no vertices were given * @see Edges::getEdgeOrder() for parameters $by and $desc * @uses self::factoryFromVertices() */ - public static function factoryCycleFromVertices($vertices, $by = null, $desc = false) + public static function factoryCycleFromVertices($vertices, $orderBy = null, $desc = false) { - $cycle = self::factoryFromVertices($vertices, $by, $desc); + $cycle = self::factoryFromVertices($vertices, $orderBy, $desc); if ($cycle->getEdges()->isEmpty()) { throw new InvalidArgumentException('Cycle with no edges can not exist'); diff --git a/tests/Set/BaseVerticesTest.php b/tests/Set/BaseVerticesTest.php index dd1f42b0..3130cfd2 100644 --- a/tests/Set/BaseVerticesTest.php +++ b/tests/Set/BaseVerticesTest.php @@ -41,6 +41,7 @@ public function testEmpty() $this->assertTrue($vertices->isEmpty()); $this->assertTrue($vertices->getVertices()->isEmpty()); $this->assertTrue($vertices->getVerticesOrder(Vertices::ORDER_ID)->isEmpty()); + $this->assertTrue($vertices->getVerticesOrder('id')->isEmpty()); $this->assertTrue($vertices->getVerticesDistinct()->isEmpty()); $this->assertTrue($vertices->getVerticesMatch(function() { })->isEmpty()); $this->assertFalse($vertices->hasDuplicates()); @@ -242,6 +243,21 @@ public function testOrderByGroup() $this->assertSame(508, $verticesOrdered->getSumCallback($sumgroups)); } + public function testOrderByAttribute() + { + $graph = new Graph(); + $v1 = $graph->createVertex()->setAttribute('votes', 20); + $v2 = $graph->createVertex()->setAttribute('votes', 10); + + $vertices = $graph->getVertices()->getVerticesOrder('votes'); + + $this->assertInstanceOf('Graphp\Graph\Set\Vertices', $vertices); + $this->assertSame($v2, $vertices->getVertexFirst()); + $this->assertSame($v1, $vertices->getVertexLast()); + + $this->assertSame($v1, $vertices->getVertexOrder('votes', true)); + } + /** * * @param Vertices $vertices diff --git a/tests/Set/EdgesTest.php b/tests/Set/EdgesTest.php index 60fb16f1..65e90506 100644 --- a/tests/Set/EdgesTest.php +++ b/tests/Set/EdgesTest.php @@ -44,6 +44,7 @@ public function testEmpty() $this->assertTrue($edges->isEmpty()); $this->assertTrue($edges->getEdges()->isEmpty()); $this->assertTrue($edges->getEdgesOrder(Edges::ORDER_WEIGHT)->isEmpty()); + $this->assertTrue($edges->getEdgesOrder('weight')->isEmpty()); $this->assertTrue($edges->getEdgesDistinct()->isEmpty()); $this->assertTrue($edges->getEdgesMatch(function() { })->isEmpty()); @@ -255,7 +256,7 @@ public function testGetEdgeOrderInvalidSortBy() $edges = $graph->getEdges(); - $edges->getEdgeOrder('not a valid callback'); + $edges->getEdgeOrder(-2); } /** @@ -265,7 +266,7 @@ public function testGetEdgesOrderInvalidSortBy() { $edges = $this->createEdges(array()); - $edges->getEdgesOrder('not a valid callback'); + $edges->getEdgesOrder(-2); } public function testOrderByGroup() @@ -298,6 +299,23 @@ public function testOrderByGroup() $this->assertSame(508, $edgesOrdered->getSumCallback($sumweights)); } + public function testOrderByAttribute() + { + $graph = new Graph(); + $v1 = $graph->createVertex(1); + $v2 = $graph->createVertex(2); + $e1 = $graph->createEdgeUndirected($v1, $v2)->setAttribute('weight', 20); + $e2 = $graph->createEdgeUndirected($v1, $v2)->setAttribute('weight', 10); + + $edges = $graph->getEdges()->getEdgesOrder('weight'); + + $this->assertInstanceOf('Graphp\Graph\Set\Edges', $edges); + $this->assertSame($e2, $edges->getEdgeFirst()); + $this->assertSame($e1, $edges->getEdgeLast()); + + $this->assertSame($e1, $edges->getEdgeOrder('weight', true)); + } + public function testIntersection() { $graph = new Graph(); diff --git a/tests/Set/VerticesTest.php b/tests/Set/VerticesTest.php index 9c13cfbe..ccca740b 100644 --- a/tests/Set/VerticesTest.php +++ b/tests/Set/VerticesTest.php @@ -30,7 +30,7 @@ public function testGetVertexOrderInvalidSortBy() $vertices = $graph->getVertices(); - $vertices->getVertexOrder('not a valid callback'); + $vertices->getVertexOrder(-1); } /** @@ -40,7 +40,7 @@ public function testGetVicesOrderInvalidSortBy() { $vertices = $this->createVertices(array()); - $vertices->getVerticesOrder('not a valid callback'); + $vertices->getVerticesOrder(-1); } public function testDuplicates() diff --git a/tests/WalkTest.php b/tests/WalkTest.php index 00823b06..5035451f 100644 --- a/tests/WalkTest.php +++ b/tests/WalkTest.php @@ -245,8 +245,8 @@ public function testFactoryFromVertices() $graph = new Graph(); $v1 = $graph->createVertex(1); $v2 = $graph->createVertex(2); - $e1 = $graph->createEdgeUndirected($v1, $v2)->setWeight(10); - $e2 = $graph->createEdgeUndirected($v1, $v2)->setWeight(20); + $e1 = $graph->createEdgeUndirected($v1, $v2)->setWeight(10)->setAttribute('weight', 10); + $e2 = $graph->createEdgeUndirected($v1, $v2)->setWeight(20)->setAttribute('weight', 20); // any edge in walk $walk = Walk::factoryFromVertices(array($v1, $v2)); @@ -255,8 +255,16 @@ public function testFactoryFromVertices() $walk = Walk::factoryFromVertices(array($v1, $v2), Edges::ORDER_WEIGHT); $this->assertSame($e1, $walk->getEdges()->getEdgeFirst()); + // edge with weight 10 + $walk = Walk::factoryFromVertices(array($v1, $v2), 'weight'); + $this->assertSame($e1, $walk->getEdges()->getEdgeFirst()); + // edge with weight 20 $walk = Walk::factoryFromVertices(array($v1, $v2), Edges::ORDER_WEIGHT, true); $this->assertSame($e2, $walk->getEdges()->getEdgeFirst()); + + // edge with weight 20 + $walk = Walk::factoryFromVertices(array($v1, $v2), 'weight', true); + $this->assertSame($e2, $walk->getEdges()->getEdgeFirst()); } }