Skip to content

Instantly share code, notes, and snippets.

@park-brian
Last active September 21, 2017 01:54
Show Gist options
  • Save park-brian/d2be949778efb5de5baf10e3dd9c50ca to your computer and use it in GitHub Desktop.
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
<?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;
}
}
<?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