Created
August 4, 2011 08:38
-
-
Save keeguon/1124739 to your computer and use it in GitHub Desktop.
Improved array Map/Reduce in PHP (wrote on the fly, need to be tested w/ real data)
This file contains hidden or 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 | |
class MapReduce | |
{ | |
/** | |
* The original data | |
* | |
* @var array | |
*/ | |
protected $data; | |
/** | |
* The original data length | |
* | |
* @var integer | |
*/ | |
protected $dataLength; | |
/** | |
* The latest mapped data | |
* | |
* @var array | |
*/ | |
protected $mappedData; | |
/** | |
* The latest reduced data | |
* | |
* @var array | |
*/ | |
protected $reducedData; | |
/** | |
* Shorthand static method to chain a map/reduce in one shot | |
* | |
* @param array $data The original data | |
* @param function $mapCallback The map callback | |
* @param function $reduceCallback The reduce callback | |
* | |
* @return array The final reduced data | |
*/ | |
public static function mapReduce($data, $mapCallback, $reduceCallback) | |
{ | |
$mapReduce = new self($data); | |
$mapReduce->map($mapCallback)->reduce($reduceCallback); | |
return $mapReduce->getReducedData(); | |
} | |
/** | |
* Constructor | |
* | |
* @param array $data The original data | |
*/ | |
public function __construct($data = null) | |
{ | |
if (!$data) { | |
throw new \Exception("InvalidConstructArgs"); | |
} | |
$this->setData($data); | |
} | |
/** | |
* Get the originale data | |
* | |
* @return array | |
*/ | |
public function getData() | |
{ | |
return $this->data; | |
} | |
/** | |
* Set the original data to be manipulated through map and reduce operations (also calculate the data length) | |
* | |
* @param array $data An array of data that will be manipulated | |
*/ | |
public function setData($data = array()) | |
{ | |
$this->data = $data; | |
$this->dataLength = count($this->data); | |
} | |
/** | |
* Returns the latest mapped data | |
* | |
* @return array | |
*/ | |
public function getMappedData() | |
{ | |
return $this->mappedData ?: array(); | |
} | |
/** | |
* Returns the latest reduced data | |
* | |
* @return array | |
*/ | |
public function getReducedData() | |
{ | |
return $this->mappedData ?: array(); | |
} | |
/** | |
* The map method | |
* | |
* @param function $mapCallback The callback function used during the map process | |
* | |
* @return \FriendSpray\Utils\MapReduce $this The current instance object, useful for chaining | |
*/ | |
public function map($mapCallback) | |
{ | |
// our map array | |
$map = array(); | |
// emit callback | |
$emit = function($key, $value) use (&$map) { | |
if (!array_key_exists($key, $map)) { | |
$map[$key] = array(); | |
} | |
array_push($map[$key], $value); | |
}; | |
for ($i = 0; $i < $this->dataLength; $i++) { | |
call_user_func($mapCallback, $this->data[$i], $emit); | |
} | |
// set mapped data | |
$this->mappedData = $map; | |
return $this; | |
} | |
/** | |
* The reduce method | |
* | |
* @return \FriendSpray\Utils\MapReduce $this The current instance object, useful for chaining | |
*/ | |
public function reduce() | |
{ | |
// Different signature usage | |
$args = func_get_args(); | |
$reduceCallback = array_pop($args); | |
$map = func_num_args() > 1 ? array_shift($args) : $this->mappedData; | |
// our reduce array | |
$reduce = array(); | |
foreach($map as $k => $v) { | |
array_push($reduce, call_user_func($reduceCallback, $k, $v)); | |
} | |
$this->reducedData = $reduce; | |
return $this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment