Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
My solution to the Array Siblings problem.
<?php
interface ArraySiblingsInterface {
public static function previous($needle, $haystack, $continueAtTop = true);
public static function next($needle, $haystack, $continueAtBottom = true);
}
class ArraySiblings implements ArraySiblingsInterface {
const FORWARD = 'fwd';
const BACKWARDS = 'bwd';
public static function previous($needle, $haystack, $continueAtTop = true) {
return self::get($needle, $haystack, self::BACKWARDS, $continueAtTop);
}
public static function next($needle, $haystack, $continueAtBottom = true) {
return self::get($needle, $haystack, self::FORWARD, $continueAtBottom);
}
private static function get($needle, $haystack, $direction = self::FORWARD, $continueAtBounds = true) {
if (!isset($haystack[$needle])) {
return null;
}
if (sizeof($haystack) == 1) {
return $continueAtBounds ? $haystack[$needle] : null;
}
if ($direction == self::FORWARD) {
return self::getNext($needle, $haystack, $continueAtBounds);
} else {
return self::getPrevious($needle, $haystack, $continueAtBounds);
}
}
private static function getNext($needle, $haystack, $continueAtBounds) {
$keys = array_keys($haystack);
$nextPosition = self::getNextPosition($needle, $keys, $continueAtBounds);
$values = array_values($haystack);
return $values[$nextPosition];
}
private static function getPrevious($needle, $haystack, $continueAtBounds) {
$keys = array_keys($haystack);
$prevPosition = self::getPreviousPosition($needle, $keys, $continueAtBounds);
$values = array_values($haystack);
return $values[$prevPosition];
}
private static function getNextPosition($needle, $keys, $continueAtBounds) {
return self::getPreviousOrNextPosition($needle, $keys, $continueAtBounds, self::FORWARD);
}
private static function getPreviousPosition($needle, $keys, $continueAtBounds) {
return self::getPreviousOrNextPosition($needle, $keys, $continueAtBounds, self::BACKWARDS);
}
private static function getPreviousOrNextPosition($needle, $keys, $continueAtBounds, $direction) {
$sizeof = sizeof($keys);
$actualPosition = array_search($needle, $keys);
$isAtBounds = self::isAtBounds($actualPosition, $sizeof, $direction);
if ((!$continueAtBounds) && ($isAtBounds)) {
return null;
}
return self::calculatePreviousOrNextPosition($actualPosition, $sizeof, $direction);
}
private static function isAtBounds($actualPosition, $sizeof, $direction) {
return ($direction == self::FORWARD) ?
($actualPosition == ($sizeof - 1)) : ($actualPosition == 0);
}
private static function calculatePreviousOrNextPosition($actualPosition, $sizeof, $direction) {
return ($direction == self::FORWARD) ?
(($actualPosition + 1) % $sizeof) : abs((($actualPosition + 1) - $sizeof));
}
}
class ArraySiblingsTest extends PHPUnit_Framework_TestCase {
protected $coll = array(
'lalala' => 1,
'pepepe' => 2,
'cocotero' => 3,
'periquito' => 4
);
public function testShouldReturnNullIfTheNeedleDoesNotExistInHaystack() {
$this->assertEquals(null, ArraySiblings::next('chuchu', $this->coll));
}
public function testShouldTheNeedleElementIfOnlyOneElementInHaystack() {
$this->assertEquals('blabla', ArraySiblings::next('chuchu', array('chuchu' => 'blabla')));
}
public function testShouldReturnNextSibling() {
$this->assertEquals(3, ArraySiblings::next('pepepe', $this->coll));
}
public function testShouldReturnPreviousSibling() {
$this->assertEquals(2, ArraySiblings::previous('cocotero', $this->coll));
}
public function testShouldGoBeyondBoundsAtTop() {
$this->assertEquals(1, ArraySiblings::next('periquito', $this->coll));
}
public function testShouldGoBeyondBoundsAtBottom() {
$this->assertEquals(4, ArraySiblings::previous('lalala', $this->coll));
}
public function testShouldReturnNullIfOnlyOneElementInArrayAndToldNotToContinueAtBounds() {
$this->assertEquals(null, ArraySiblings::next('chuchu', array('chuchu' => 'blabla'), false));
$this->assertEquals(null, ArraySiblings::previous('chuchu', array('chuchu' => 'blabla'), false));
}
public function testShouldReturnNullIfToldNotToContinueAtTop() {
$this->assertEquals(null, ArraySiblings::next('periquito', $this->coll, false));
}
public function testShouldReturnNullIfToldNotToContinueAtBottom() {
$this->assertEquals(null, ArraySiblings::previous('lalala', $this->coll, false));
}
}
@ggalmazor

Súper interesante cómo usar el operador % para dar la vuelta al final del array con:

$pos_siguiente = (($pos_actual + 1) % $sizeof);

Me la apunto!

@rmhdev
Owner

He refactorizado el código, que había un poco de "code smell" ;) A ver si la gente se anima y aporta soluciones!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.