Created
March 23, 2011 20:23
-
-
Save rmhdev/883875 to your computer and use it in GitHub Desktop.
My solution to the Array Siblings problem.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
He refactorizado el código, que había un poco de "code smell" ;) A ver si la gente se anima y aporta soluciones!