Last active
August 29, 2015 14:23
-
-
Save Leko/f2b090fe14f51dbea841 to your computer and use it in GitHub Desktop.
PHPでもRubyみたいに..や...で範囲アクセスしたかった...おまけでインデックスの反転も実装しています。
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 Ary implements \ArrayAccess | |
{ | |
protected $list; | |
public function __construct(/* $args... */) | |
{ | |
$this->list = func_get_args(); | |
} | |
public function offsetExists($offset) | |
{ | |
// Undefined offset ** を渡された値にするため0以上になる場合のみインデックスを逆転する | |
if(is_int($offset) && $offset < 0 && $offset + count($this->list) >= 0) { | |
$offset += count($this->list); | |
} | |
return isset($this->list[$offset]); | |
} | |
public function offsetGet($offset) | |
{ | |
list($from, $to) = $this->parseOffset($offset); | |
if($from === $to) { | |
$ret = $this->list[$from]; | |
} else { | |
$ret = array(); | |
for($ii = $from; $ii <= $to; $ii++) $ret[] = $this->list[$ii]; | |
} | |
return $ret; | |
} | |
public function offsetSet($offset, $value) | |
{ | |
list($from, $to) = $this->parseOffset($offset); | |
if($from === $to) { | |
$this->list[$from] = $value; | |
} elseif(is_array($value)) { | |
for($ii = $from; $ii <= $to; $ii++) $this->list[$ii] = $value[$ii - $from]; | |
} else { | |
for($ii = $from; $ii <= $to; $ii++) $this->list[$ii] = $value; | |
} | |
} | |
public function offsetUnset($offset) | |
{ | |
list($from, $to) = $this->parseOffset($offset); | |
if($from === $to) { | |
unset($this->list[$from]); | |
} else { | |
for($ii = $from; $ii <= $to; $ii++) unset($this->list[$ii]); | |
} | |
} | |
private function parseOffset($offset) | |
{ | |
// Undefined offset ** を渡された値にするため0以上になる場合のみインデックスを逆転する | |
if(is_int($offset) && $offset < 0 && $offset + count($this->list) >= 0) { | |
$offset += count($this->list); | |
} | |
if(is_string($offset) && strpos($offset, '..') >= 0) { | |
preg_match('/^([0-9]+)(\.\.\.?)([0-9]+)$/', $offset, $matches); | |
list($_, $from, $op, $to) = $matches; | |
if($op === '..') $to--; | |
return [$from, $to]; | |
} else { | |
return [$offset, $offset]; | |
} | |
} | |
} | |
// PHPのarray()と同じように中の要素を列挙して可変長引数として渡す | |
$list = new Ary(1, 2, 3, 4, 5); | |
// 普通の添字アクセス1 | |
var_dump(isset($list[1]), $list[1]); | |
echo '------------'.PHP_EOL; | |
// 普通の添字アクセス2 | |
var_dump(isset($list[0]), $list[0]); | |
echo '------------'.PHP_EOL; | |
// マイナス添字でのアクセス1(後ろから見る) | |
var_dump(isset($list[-1]), $list[-1]); | |
echo '------------'.PHP_EOL; | |
// マイナス添字でのアクセス2(後ろから見る) | |
var_dump(isset($list[-5]), $list[-5]); | |
echo '------------'.PHP_EOL; | |
// マイナスでも存在しない添字に遭遇した場合Noticeが出る | |
var_dump(isset($list[-6]), $list[-6]); | |
echo '------------'.PHP_EOL; | |
// .. = 1以上3未満の範囲アクセス | |
var_dump($list['1..3']); | |
echo '------------'.PHP_EOL; | |
// ... = 1以上3以下の範囲アクセス | |
var_dump($list['1...3']); | |
echo '------------'.PHP_EOL; | |
// ...を使用した一括代入。配列を指定すると各要素に対応する値を入れる | |
$list['1...3'] = [20, 30, 40]; | |
var_dump($list); | |
echo '------------'.PHP_EOL; | |
// 範囲ごとの一括指定が可能。配列以外の値を指定すると範囲内全てがその値に | |
$list['1..3'] = 1000; | |
var_dump($list); | |
echo '------------'.PHP_EOL; | |
// 一括unset | |
unset($list['3..5']); | |
var_dump($list); | |
echo '------------'.PHP_EOL; |
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
bool(true) | |
int(2) | |
------------ | |
bool(true) | |
int(1) | |
------------ | |
bool(true) | |
int(5) | |
------------ | |
bool(true) | |
int(1) | |
------------ | |
PHP Notice: Undefined offset: -6 in /Users/SYS-INOUE/Downloads/range.php on line 27 | |
PHP Stack trace: | |
PHP 1. {main}() /Users/SYS-INOUE/Downloads/range.php:0 | |
PHP 2. Ary->offsetGet() /Users/SYS-INOUE/Downloads/range.php:93 | |
Notice: Undefined offset: -6 in /Users/SYS-INOUE/Downloads/range.php on line 27 | |
Call Stack: | |
0.0005 256088 1. {main}() /Users/SYS-INOUE/Downloads/range.php:0 | |
0.0013 257648 2. Ary->offsetGet() /Users/SYS-INOUE/Downloads/range.php:93 | |
bool(false) | |
NULL | |
------------ | |
array(2) { | |
[0] => | |
int(2) | |
[1] => | |
int(3) | |
} | |
------------ | |
array(3) { | |
[0] => | |
int(2) | |
[1] => | |
int(3) | |
[2] => | |
int(4) | |
} | |
------------ | |
class Ary#1 (1) { | |
protected $list => | |
array(5) { | |
[0] => | |
int(1) | |
[1] => | |
int(20) | |
[2] => | |
int(30) | |
[3] => | |
int(40) | |
[4] => | |
int(5) | |
} | |
} | |
------------ | |
class Ary#1 (1) { | |
protected $list => | |
array(5) { | |
[0] => | |
int(1) | |
[1] => | |
int(1000) | |
[2] => | |
int(1000) | |
[3] => | |
int(40) | |
[4] => | |
int(5) | |
} | |
} | |
------------ | |
class Ary#1 (1) { | |
protected $list => | |
array(3) { | |
[0] => | |
int(1) | |
[1] => | |
int(1000) | |
[2] => | |
int(1000) | |
} | |
} | |
------------ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment