Last active
April 26, 2016 16:30
-
-
Save chiyoyo/43b87c1bf6e1429a9b67 to your computer and use it in GitHub Desktop.
汎用ツリー構造クラスを作ってみた ref: http://qiita.com/chiyoyo/items/f06e4d3f3e39d4238bca
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 | |
class TreeNode | |
{ | |
/** 本オブジェクトの親要素 */ | |
private $parent; | |
/** 本オブジェクトの子要素 */ | |
private $children = []; | |
/** 名前 */ | |
private $name; | |
/** 値 */ | |
public $value; | |
/** | |
* コンストラクタ | |
* | |
* @param string $name 名前(親の場合は省略可能) | |
*/ | |
public function __construct($name = null) | |
{ | |
$this->name = $name; | |
} | |
/** | |
* 子を追加する | |
* すでに同名のものがある場合は追加しない | |
* | |
* @param string $name 追加する子要素 | |
* @return TreeNode 追加した子要素 | |
*/ | |
public function append($name) | |
{ | |
$child = $this->child($name); | |
if ($child === false) { | |
$child = new TreeNode($name); | |
$child->parent = $this; | |
$this->children[$child->name] = $child; | |
} | |
return $child; | |
} | |
/** | |
* 指定した子を削除する | |
* | |
* @param string $name 削除する子要素 | |
* @return TreeNode 自分自身 | |
*/ | |
public function remove($name) | |
{ | |
if ($this->has($name)) { | |
unset($this->children[$name]); | |
} | |
return $this; | |
} | |
/** | |
* 指定した名前の子要素を取得する | |
* | |
* @param string $name 名前(省略時は全部) | |
* @return TreeNode | array | boolean | |
*/ | |
public function child($name = null) | |
{ | |
// 引数省略時は全部 | |
if (is_null($name)) { | |
return $this->children; | |
} | |
// 引数指定時は指定した名前の子要素 | |
if (!$this->has($name)) { | |
return false; | |
} | |
return $this->children[$name]; | |
} | |
/** | |
* 指定した名前の子要素があるかどうか | |
* 省略時は子要素自体があるかどうか | |
* | |
* @param string $name 名前 | |
* @return boolean | |
*/ | |
public function has($name) | |
{ | |
// 引数省略時 | |
if (is_null($name)) { | |
return (0 < count($this->children)); | |
} | |
return isset($this->children[$name]); | |
} | |
/** | |
* 名前を取得 | |
* @return string | |
*/ | |
public function name() | |
{ | |
return $this->name; | |
} | |
/** | |
* 親要素を取得 | |
* | |
* @return TreeNode 親要素 | |
*/ | |
public function parent() | |
{ | |
return $this->parent; | |
} | |
/** | |
* パスの配列を取得する | |
* valueは含まれません | |
* 例: [NULL, 'HOGE', 'FUGA'] | |
* | |
* @return array | |
*/ | |
public function path() | |
{ | |
$result = [$this->name]; | |
$parent = $this->parent; | |
while($parent != null) { | |
$result[] = $parent->name; | |
$parent = $parent->parent; | |
} | |
$result = array_reverse($result); | |
return $result; | |
} | |
} |
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
// 親ノード作成 | |
$tree = new TreeNode(); | |
// 子ノードを追加して子の値を設定 | |
// 親 > HOGE = 123 | |
$tree->append('HOGE')->value = 123; | |
// 子ノードを追加して、更にその下に子ノードを追加して | |
// 親 > HOGE > FUGA | |
$tree->append('HOGE')->append("FUGA"); | |
// 子ノードHOGEの下にある子ノードFUGAを取得 | |
$fuga = $tree->child('HOGE')->child('FUGA'); | |
// 子ノードHOGEを追加して、それを削除(親ノードしか残ってない) | |
$tree->append('HOGE')->parent()->remove('HOGE') | |
// 「/」区切りのパス文字列を取得(/HOGE/FUGA) | |
echo implode('/', $tree->append('HOGE')->append('FUGA')->path()); |
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
/** | |
* 文字列をセパレータで分割したものをtree情報化する | |
* | |
* @param char $separator セパレータ文字 | |
* @param string $string 文字列 | |
* @return TreeNode TreeNode親要素 | |
*/ | |
public static function fromString($separator, $string) | |
{ | |
// セパレータが特殊文字の場合はエスケープ | |
$sep = $separator; | |
if ($sep == '/' || $sep == '\\') { | |
$sep = '\\' . $sep; | |
} | |
// 先頭のセパレータを除去 | |
$string = preg_replace('/^' . $sep . '/', '', $string); | |
$list = explode($separator, $string); | |
$tree = null; | |
foreach ($list as $str) { | |
if ($tree === null) { | |
$tree = new TreeNode($str); | |
} else { | |
$tree = $tree->append($str); | |
} | |
} | |
return $tree; | |
} |
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
$tree = TreeNode('/', 'hoge/fuga'); | |
var_dump($tree->path()) | |
// array(2) { [0]=> string(4) "hoge" [1]=> string(4) "fuga" } | |
$tree = TreeNode('/', '/hoge/fuga'); | |
var_dump($tree->path()) | |
// array(3) { [0]=> string(0) "" [1]=> string(4) "hoge" [2]=> string(4) "fuga" } |
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 | |
class TreeNode | |
{ | |
/** 本オブジェクトの親要素 */ | |
private $parent; | |
/** 本オブジェクトの子要素 */ | |
private $children = []; | |
/** 名前 */ | |
private $name; | |
/** 値 */ | |
public $value; | |
/** | |
* コンストラクタ | |
* | |
* @param string $name 名前(親の場合は省略可能) | |
*/ | |
public function __construct($name = null) | |
{ | |
$this->name = $name; | |
} | |
/** | |
* 子を追加する | |
* すでに同名のものがある場合は追加しない | |
* | |
* @param string $name 追加する子要素 | |
* @return TreeNode 追加した子要素 | |
*/ | |
public function append($name) | |
{ | |
$child = $this->child($name); | |
if ($child === false) { | |
$child = new TreeNode($name); | |
$child->parent = $this; | |
$this->children[$child->name] = $child; | |
} | |
return $child; | |
} | |
/** | |
* 指定した子を削除する | |
* | |
* @param string $name 削除する子要素 | |
* @return TreeNode 自分自身 | |
*/ | |
public function remove($name) | |
{ | |
if ($this->has($name)) { | |
unset($this->children[$name]); | |
} | |
return $this; | |
} | |
/** | |
* 指定した名前の子要素を取得する | |
* | |
* @param string $name 名前(省略時は全部) | |
* @return TreeNode | array | boolean | |
*/ | |
public function child($name = null) | |
{ | |
// 引数省略時は全部 | |
if (is_null($name)) { | |
return $this->children; | |
} | |
// 引数指定時は指定した名前の子要素 | |
if (!$this->has($name)) { | |
return false; | |
} | |
return $this->children[$name]; | |
} | |
/** | |
* 指定した名前の子要素があるかどうか | |
* 省略時は子要素自体があるかどうか | |
* | |
* @param string $name 名前 | |
* @return boolean | |
*/ | |
public function has($name = null) | |
{ | |
// 引数省略時 | |
if (is_null($name)) { | |
return (0 < count($this->children)); | |
} | |
return isset($this->children[$name]); | |
} | |
/** | |
* 名前を取得 | |
* @return string | |
*/ | |
public function name() | |
{ | |
return $this->name; | |
} | |
/** | |
* 親要素を取得 | |
* | |
* @return TreeNode 親要素 | |
*/ | |
public function parent() | |
{ | |
return $this->parent; | |
} | |
/** | |
* パスの配列を取得する | |
* valueは含まれません | |
* 例: [NULL, 'HOGE', 'FUGA'] | |
* | |
* @return array | |
*/ | |
public function path() | |
{ | |
$result = [$this->name]; | |
$parent = $this->parent; | |
while($parent != null) { | |
$result[] = $parent->name; | |
$parent = $parent->parent; | |
} | |
$result = array_reverse($result); | |
return $result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment