Skip to content

Instantly share code, notes, and snippets.

@keeguon
Created August 4, 2011 08:38
Show Gist options
  • Save keeguon/1124739 to your computer and use it in GitHub Desktop.
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)
<?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