Last active
September 21, 2017 01:54
-
-
Save park-brian/d2be949778efb5de5baf10e3dd9c50ca to your computer and use it in GitHub Desktop.
A simple class that wraps a PHP array in a "functional" way
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 | |
/** | |
* A simple class that wraps a PHP array in a functional way. | |
* | |
* Example Usage: | |
* | |
* $val = (new FunctionalArray(range(1, 10))) | |
* ->map (function($value) { return $value * 1; }) | |
* ->filter (function($value) { return $value > 5; }) | |
* ->reduce (function($acc, $curr) { return $acc + $curr; }, 0); | |
* | |
* print_r($val); | |
*/ | |
class FunctionalArray implements ArrayAccess, Iterator, JsonSerializable { | |
private $array = []; | |
private $keys = []; | |
private $position = null; | |
public function __construct($array = []) { | |
$this->array = $array; | |
$this->keys = array_keys($array); | |
$this->position = array_key_exists(0, $this->keys) | |
? $this->keys[0] | |
: null; | |
} | |
public function map($callback) { | |
$new = []; | |
foreach($this->array as $key => $value) { | |
$new[$key] = $callback($value, $key); | |
} | |
return new FunctionalArray($new); | |
} | |
public function filter($callback) { | |
$result = array_filter($this->array, $callback, ARRAY_FILTER_USE_BOTH); | |
return new FunctionalArray( | |
self::has_string_keys($this->array) | |
? $result | |
: array_values($result) | |
); | |
} | |
public function reduce($callback, $initialValue = NULL) { | |
$accumulator = $initialValue; | |
foreach($this->array as $key => $value) { | |
$accumulator = $callback($accumulator, $value, $key); | |
} | |
return is_array($accumulator) | |
? new FunctionalArray($accumulator) | |
: $accumulator; | |
} | |
public function get() { | |
return $this->array; | |
} | |
public function offsetExists($offset) { | |
return array_key_exists($offset, $this->array); | |
} | |
public function offsetGet($offset) { | |
return $this->array[$offset]; | |
} | |
public function offsetSet($offset, $value) { | |
$this->array[$offset] = $value; | |
} | |
public function offsetUnset($offset) { | |
unset($this->array[$offset]); | |
} | |
public function rewind() { | |
$this->position = 0; | |
} | |
public function current() { | |
return $this->array[ | |
$this->keys[$this->position] | |
]; | |
} | |
public function key() { | |
return $this->keys[$this->position]; | |
} | |
public function next() { | |
++$this->position; | |
} | |
public function valid() { | |
return | |
isset($this->keys[$this->position]) && | |
isset($this->array[ | |
$this->keys[$this->position] | |
]); | |
} | |
public function jsonSerialize() { | |
return json_encode($this->array); | |
} | |
private static function has_string_keys(array $array) { | |
return count(array_filter(array_keys($array), 'is_string')) > 0; | |
} | |
} |
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 | |
include 'FunctionalArray.php'; | |
####################################### | |
## Map/Filter/Reduce using numeric keys | |
####################################### | |
$factor = 2; | |
$numbers = (new FunctionalArray(range(1, 10))) | |
->map (function($value) use ($factor) { return $value * $factor; }) | |
->filter (function($value) { return $value >= 10; }); | |
print_r($numbers->get()); | |
## Output: | |
## Array | |
## ( | |
## [0] => 10 | |
## [1] => 12 | |
## [2] => 14 | |
## [3] => 16 | |
## [4] => 18 | |
## [5] => 20 | |
## ) | |
########################################### | |
## Map/Filter/Reduce using associative keys | |
########################################### | |
$fruitRatings = [ | |
'apple' => 70, | |
'banana' => 80, | |
'cherry' => 90, | |
'dragonfruit' => 100 | |
]; | |
$favoriteFruits = (new FunctionalArray($fruitRatings)) | |
->filter(function($value) { return $value >= 80; }) | |
->map(function($value, $key) { return "($value)"; }) | |
->reduce(function($acc, $value, $key) { | |
return implode("\n", [$acc, "$key $value"]); | |
}, "My favorite fruits:"); | |
echo "\n" . $favoriteFruits; | |
## Output: | |
## My favorite fruits: | |
## banana (80) | |
## cherry (90) | |
## dragonfruit (100) | |
######################### | |
## Implements ArrayAccess | |
######################### | |
$names = new FunctionalArray([ | |
'Alex', | |
'Bailey', | |
'Cameron', | |
'Darcy', | |
'Erin', | |
]); | |
echo "\n\nNames: "; | |
print_r($names->get()); | |
echo '$names[0]: ' . "$names[0] \n"; | |
echo '$names[4]: ' . "$names[4] \n"; | |
## Output: | |
## Names: Array | |
## ( | |
## [0] => Alex | |
## [1] => Bailey | |
## [2] => Cameron | |
## [3] => Darcy | |
## [4] => Erin | |
## ) | |
## $names[0]: Alex | |
## $names[4]: Erin | |
###################### | |
## Implements Iterator | |
###################### | |
$names = new FunctionalArray([ | |
'a' => 'Alpha', | |
'b' => 'Bravo', | |
'c' => 'Charlie', | |
'd' => 'Delta', | |
'e' => 'Echo', | |
'f' => 'Foxtrot', | |
]); | |
echo "\n\nNATO Names: \n"; | |
foreach($names as $letter => $name) { | |
echo "$letter: $name \n"; | |
} | |
## Output: | |
## NATO Names: | |
## a: Alpha | |
## b: Bravo | |
## c: Charlie | |
## d: Delta | |
## e: Echo | |
## f: Foxtrot | |
############################## | |
## Implements JsonSerializable | |
############################## | |
echo "\nSerialize as JSON: "; | |
$data = new FunctionalArray([ | |
'a' => 1, | |
'b' => 2, | |
]); | |
echo json_encode($data); | |
## Output: | |
## Serialize as JSON: "{\"a\":1,\"b\":2}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment