Skip to content

Instantly share code, notes, and snippets.

@yosugi
Created August 26, 2021 05:27
Show Gist options
  • Select an option

  • Save yosugi/b68a96eaab5f6351daa52bf95cca7fe8 to your computer and use it in GitHub Desktop.

Select an option

Save yosugi/b68a96eaab5f6351daa52bf95cca7fe8 to your computer and use it in GitHub Desktop.
<?php
namespace DataRenovationBundle\Util;
use ArrayObject;
/**
* DataRenovationBundle\Utils\ArrayUtil
*
* 配列に関わるユーティリティ
*/
class ArrayUtil extends ArrayObject
{
public function __construct(array $array)
{
parent::__construct($array);
}
public static function init(array $array)
{
return new self($array);
}
public function toArray()
{
return (array) $this;
}
/**
* 配列に指定されたキーがあればその値を、なければ default を返す
*
* @param mixed $key
* @param bool $default
* @param $predicate 何も指定しない場合 isset(),
* true の場合 array_key_exists()
* callable を指定した場合指定したもので判定する
* @static
* @return mixed
*
* 使用例
*
* $array = ['a', 'b', null];
*
* get($array, 0); // => 'a'
* get($array, 3); // => null
* get($array, 2, 'default'); // => 'default'
* get($array, 2, 'default', true); // => null
*/
protected static function get($input, $key, $default = null, $predicate = null)
{
$restKey = [];
if (is_array($key)) {
$restKey = $key;
$key = array_shift($restKey);
}
// isset で判定する場合
if (is_null($predicate)) {
$predicate = function ($array, $key) {
return isset($array[$key]);
};
}
// predicate で判定する場合
if (!is_callable($predicate)) {
$predicate = function ($array, $key) {
return array_key_exists($key, $array);
};
}
$value = (call_user_func($predicate, $input, $key)) ? $input[$key] : $default;
if (empty($restKey)) return $value;
if (!is_array($value)) return $default;
return self::get($value, $restKey, $default, $predicate);
}
/**
* 最初の null でない引数を返す
* 全て null の場合は null を返す
*
* @static
* @return mixed
*
* 例
* coalesce(null, 0, 1) // -> 0
* coalesce(null, null, 'a', 'b') // -> 'a'
* coalesce(null, '', 'a', 'b') // -> ''
*/
public static function coalesce()
{
$args = func_get_args();
// 最初の null でないものを返す
return self::find($args, function ($value) {
return !is_null($value);
});
}
/**
* 配列中で最初に $predicate を満たした値を返す
* なかった場合、$notFound を返す
*
* @param callable $predicate
* @param mixed $notFound
* @static
* @return mixed
*
* 例
* find([null, 0, 1]) // -> 1
* find(['', 1, 2]) // -> 1
* find([null, 0, '']) // -> null
* find(['a', 'b', '2'], 'is_numeric') // -> '2'
* find(['a', 'b', 'c'], 'is_numeric') // -> null
* find(['a', 'b', 'c'], 'is_numeric', 'not found') // -> 'not found'
*/
protected static function find($input, callable $predicate = null, $notFound = null)
{
// デフォルトは真になるものを返す
if (!is_callable($predicate)) {
$predicate = function ($value) {
return (boolean) $value;
};
}
// predicate を満たすものが見つかれば返す
foreach ($input as $value) {
$ret = call_user_func($predicate, $value);
if ($ret) return $value;
}
// なければ $notFound を返す
return $notFound;
}
/**
* 配列の要素に function を適用する
*
* @param mixed $input
* @param callable $function
* @static
* @return void
*/
protected static function map($input, callable $function)
{
$output = [];
foreach ($input as $key => $value) {
$output[$key] = call_user_func($function, $value, $key);
}
return $output;
}
/**
* 配列の要素に function を適用する(キーも含む)
*
* @param mixed $input
* @param callable $function
* @static
* @return void
*/
protected function mapWithKey($input, callable $function)
{
$output = [];
foreach ($input as $key => $value) {
$result = call_user_func($function, $key, $value);
$output[key($result)] = current($result);
}
return $output;
}
/**
* コールバック関数が true を返す要素のみ残す
*
* @param mixed $input
* @param callable $predicate
* @static
* @return void
*/
protected static function filter($input, callable $predicate = null)
{
if ($predicate == null) {
$predicate = function ($val) {return $val;};
}
$output = [];
foreach ($input as $key => $value) {
if (!call_user_func($predicate, $value, $key)) continue;
$output[$key] = $value;
}
return $output;
}
public function __call($name, $arguments)
{
if (!method_exists($this, $name)) {
throw new \Exception('Call to undefined method ArrayUtil::' . $name);
}
array_unshift($arguments, $this);
$result = call_user_func_array([$this, $name], $arguments);
if (in_array($name, ['get', 'find'])) return $result;
return ($result instanceof self) ? $result : new self($result);
}
public static function __callStatic($name, $arguments)
{
if (!method_exists(__CLASS__, $name)) {
throw new BadMethodCallException('Call to undefined method ArrayUtil->' . $name);
}
return call_user_func_array([__CLASS__, $name], $arguments);
}
}
/**
* test code
*/
if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])) {
$array = [
'a' => 1,
'b' => 2,
'c' => 3,
'd' => [
'a' => 1,
'b' => 2,
],
];
assert(1 === ArrayUtil::get($array, 'a'));
assert(1 === ArrayUtil::init($array)->get('a'));
assert(null === ArrayUtil::get($array, 'nothing'));
assert('default' === ArrayUtil::get($array, 'nothing', 'default'));
assert(1 === ArrayUtil::get($array, ['a']));
$expect = [
'a' => 1,
'b' => 2,
];
assert($expect === ArrayUtil::get($array, 'd'));
assert($expect === ArrayUtil::get($array, ['d']));
assert(null === ArrayUtil::get($array, ['a', 'b']));
assert(2 === ArrayUtil::get($array, ['d', 'b']));
assert('default' === ArrayUtil::get($array, ['d', 'c'], 'default'));
assert(1 === ArrayUtil::find([null, 0, 1]));
assert(1 === ArrayUtil::init([null, 0, 1])->find());
assert(1 === ArrayUtil::find(['', 1, 2]));
assert(null === ArrayUtil::find([null, 0, '']));
assert('2' === ArrayUtil::find(['a', 'b', '2'], 'is_numeric'));
assert(null === ArrayUtil::find(['a', 'b', 'c'], 'is_numeric'));
assert('not found' === ArrayUtil::find(['a', 'b', 'c'], 'is_numeric', 'not found'));
assert(0 === ArrayUtil::coalesce(null, 0, 1));
assert('a' === ArrayUtil::coalesce(null, null, 'a', 'b'));
assert('' === ArrayUtil::coalesce(null, '', 'a', 'b'));
$array = [
'a' => 1,
'b' => 2,
'c' => 3,
];
$expect = [
'a' => 1,
'c' => 3,
];
$ret = ArrayUtil::filter($array, function ($value) {
return $value % 2;
});
assert($expect === $ret);
$array = [
'a' => 1,
'b' => 2,
'c' => 3,
];
$expect = [
'a' => 2,
'c' => 6,
];
$ret = ArrayUtil::init($array)->filter(function ($value) {
return $value % 2;
})->map(function ($value) {
return $value * 2;
})->toArray();
assert($expect === $ret);
$array = [
'a' => 1,
'b' => 2,
'c' => 3,
];
$expect = [
'a' . 'a' => 1 + 1,
'b' . 'b' => 2 + 2,
'c' . 'c' => 3 + 3,
];
$ret = ArrayUtil::init($array)->mapWithKey(function ($key, $value) {
return [$key . $key => $value + $value];
})->toArray();
assert($expect === $ret);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment