Created
June 29, 2012 16:16
-
-
Save hakre/3018902 to your computer and use it in GitHub Desktop.
convert tab/space delimited lines into nested array
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 | |
/** | |
* convert tab/space delimited lines into nested array | |
* @link http://stackoverflow.com/q/9797261/367456 | |
* @author hakre <http://hakre.wordpress.com> | |
*/ | |
$input = <<<STR | |
cat, true cat | |
=> domestic cat, house cat, Felis domesticus, Felis catus | |
=> kitty, kitty-cat, puss | |
=> mouser | |
=> alley cat | |
=> tom, tomcat | |
=> gib | |
=> Angora, Angora cat | |
=> Siamese cat, Siamese | |
=> blue point Siamese | |
=> wildcat | |
=> sand cat | |
=> European wildcat, catamountain, Felis silvestris | |
=> cougar, puma, catamount, mountain lion, painter, panther, Felis concolor | |
=> ocelot, panther cat, Felis pardalis | |
=> manul, Pallas's cat, Felis manul | |
=> lynx, catamount | |
=> common lynx, Lynx lynx | |
=> Canada lynx, Lynx canadensis | |
STR; | |
// build tree | |
$tree = $levels = array(); | |
$stack[1] = &$tree; | |
for ($line = strtok($input, $token = "\n"); $line; $line = strtok($token)) { | |
if (!preg_match('/^(?:(\s*)=> )?(.*)$/', $line, $self)) { | |
continue; | |
} | |
array_shift($self); | |
$indent = array_shift($self); | |
$level = @$levels[$indent] ? : $levels[$indent] = count($levels) + 1; | |
$stack[$level][] = &$self; | |
$stack[$level + 1] = &$self[]; | |
unset($self); | |
} | |
unset($stack); | |
// output | |
tree_print($tree); | |
function tree_print(array $tree, $in = '') { | |
echo "$in<ul>\n"; | |
$i = $in . ' '; | |
foreach ($tree as $n) | |
printf("</li>\n", printf("$i<li>$n[0]") && $n[1] && printf($i, printf("\n") & tree_print($n[1], "$i "))); | |
echo "$in</ul>\n"; | |
} |
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 | |
/** | |
* convert tab/space delimited lines into nested array | |
* @link http://stackoverflow.com/q/9797261/367456 | |
* @author hakre <http://hakre.wordpress.com> | |
*/ | |
$input = <<<STR | |
cat, true cat | |
=> domestic cat, house cat, Felis domesticus, Felis catus | |
=> kitty, kitty-cat, puss | |
=> mouser | |
=> alley cat | |
=> tom, tomcat | |
=> gib | |
=> Angora, Angora cat | |
=> Siamese cat, Siamese | |
=> blue point Siamese | |
=> wildcat | |
=> sand cat | |
=> European wildcat, catamountain, Felis silvestris | |
=> cougar, puma, catamount, mountain lion, painter, panther, Felis concolor | |
=> ocelot, panther cat, Felis pardalis | |
=> manul, Pallas's cat, Felis manul | |
=> lynx, catamount | |
=> common lynx, Lynx lynx | |
=> Canada lynx, Lynx canadensis | |
STR; | |
echo_list($input); | |
function echo_list($string) { | |
foreach ($m = array_map(function($v) use (&$l) { | |
return array(@$l[$i = &$v[1]] ? : $l[$i] = count($l) + 1, $v[2]); | |
}, preg_match_all('/^(?:(\s*)=> )?(.*)$/m', $string, $m, PREG_SET_ORDER) ? $m : array()) as $i => $v) { | |
$pi = str_repeat(" ", $pl = @$m[$i - 1][0]); # prev | |
$ni = str_repeat(" ", $nl = @$m[$i + 1][0]); # next | |
(($v[0] - $pl) > 0) && printf("$pi<ul>\n"); # is child of prev | |
echo ' ' . str_repeat(" ", $v[0] - 1), "<li>$v[1]"; # output self | |
if (!$close = (($nl - $v[0]) * -1)) echo "</li>\n"; # has sibling | |
else if ($close < 0) echo "\n"; # has children | |
else for (printf("</li>\n$ni" . str_repeat(" ", $close - 1) . "</ul>\n"); --$close;) # is last child | |
echo $ni, $nn = str_repeat(" ", $close - 1), " </li>\n", | |
$ni, $nn, "</ul>\n"; | |
} | |
} |
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 | |
/** | |
* convert tab/space delimited lines into nested array | |
* @link http://stackoverflow.com/q/9797261/367456 | |
* @author hakre <http://hakre.wordpress.com> | |
*/ | |
$input = <<<STR | |
cat, true cat | |
=> domestic cat, house cat, Felis domesticus, Felis catus | |
=> kitty, kitty-cat, puss | |
=> mouser | |
=> alley cat | |
=> tom, tomcat | |
=> gib | |
=> Angora, Angora cat | |
=> Siamese cat, Siamese | |
=> blue point Siamese | |
=> wildcat | |
=> sand cat | |
=> European wildcat, catamountain, Felis silvestris | |
=> cougar, puma, catamount, mountain lion, painter, panther, Felis concolor | |
=> ocelot, panther cat, Felis pardalis | |
=> manul, Pallas's cat, Felis manul | |
=> lynx, catamount | |
=> common lynx, Lynx lynx | |
=> Canada lynx, Lynx canadensis | |
STR; | |
/** | |
* Levels for indent strings | |
*/ | |
class Levels | |
{ | |
private $levels = array(); | |
public function __invoke($str) | |
{ | |
$number = strlen($str); | |
$key = array_search($number, $this->levels, true); | |
if ($key !== false) { | |
return $key; | |
} | |
$key = count($this->levels); | |
if ($key && $number < $this->levels[$key - 1]) { | |
throw new InvalidArgumentException(sprintf( | |
'The number given %d is not a level yet but below the range of levels which ends at %d.', | |
$number, $this->levels[$key - 1] | |
)); | |
} | |
$this->levels[$key] = $number; | |
return $key; | |
} | |
} | |
/** | |
* preg match as array | |
* | |
* @param $string | |
* @param string $pattern pcre regular expression pattern. | |
* @return array | |
*/ | |
$matches = function($string, $pattern) | |
{ | |
return preg_match_all($pattern, $string, $matches, PREG_SET_ORDER) | |
? $matches : array(); | |
}; | |
$map = function(Levels $levels) | |
{ | |
return function (array $match) use ($levels) | |
{ | |
list(, $indent, $name) = $match; | |
$level = $levels($indent); | |
return array($level, $name); | |
}; | |
}; | |
$map = $map(new Levels()); | |
$tree = array(); | |
$stack = function(array &$tree) | |
{ | |
$stack[] = &$tree; | |
return function($level, $element) use (&$stack) | |
{ | |
$self = array($element, array()); | |
$stack[$level][] = &$self; | |
$stack[$level + 1] = &$self[1]; | |
}; | |
}; | |
$push = $stack($tree); | |
foreach ($matches($input, '/^(?:(\s*)=> )?(.*)$/m') as $match) { | |
list($level, $element) = $map($match); | |
$push($level, $element); | |
} | |
class TreeIterator extends ArrayIterator implements RecursiveIterator | |
{ | |
private $current; | |
public function __construct($node) | |
{ | |
parent::__construct($node); | |
} | |
public function current() | |
{ | |
$this->current = parent::current(); | |
return $this->current[0]; | |
} | |
public function hasChildren() | |
{ | |
return !empty($this->current[1]); | |
} | |
public function getChildren() | |
{ | |
return new self($this->current[1]); | |
} | |
} | |
$treeIterator = new RecursiveTreeIterator( | |
new TreeIterator($tree)); | |
foreach ($treeIterator as $val) echo $val, "\n"; |
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
array ( | |
0 => | |
array ( | |
0 => 'cat, true cat', | |
1 => | |
array ( | |
0 => | |
array ( | |
0 => 'domestic cat, house cat, Felis domesticus, Felis catus', | |
1 => | |
array ( | |
0 => | |
array ( | |
0 => 'kitty, kitty-cat, puss', | |
1 => NULL, | |
), | |
1 => | |
array ( | |
0 => 'mouser', | |
1 => NULL, | |
), | |
2 => | |
array ( | |
0 => 'alley cat', | |
1 => NULL, | |
), | |
3 => | |
array ( | |
0 => 'tom, tomcat', | |
1 => | |
array ( | |
0 => | |
array ( | |
0 => 'gib', | |
1 => NULL, | |
), | |
), | |
), | |
4 => | |
array ( | |
0 => 'Angora, Angora cat', | |
1 => NULL, | |
), | |
5 => | |
array ( | |
0 => 'Siamese cat, Siamese', | |
1 => | |
array ( | |
0 => | |
array ( | |
0 => 'blue point Siamese', | |
1 => NULL, | |
), | |
), | |
), | |
), | |
), | |
1 => | |
array ( | |
0 => 'wildcat', | |
1 => | |
array ( | |
0 => | |
array ( | |
0 => 'sand cat', | |
1 => NULL, | |
), | |
1 => | |
array ( | |
0 => 'European wildcat, catamountain, Felis silvestris', | |
1 => NULL, | |
), | |
2 => | |
array ( | |
0 => 'cougar, puma, catamount, mountain lion, painter, panther, Felis concolor', | |
1 => NULL, | |
), | |
3 => | |
array ( | |
0 => 'ocelot, panther cat, Felis pardalis', | |
1 => NULL, | |
), | |
4 => | |
array ( | |
0 => 'manul, Pallas\'s cat, Felis manul', | |
1 => NULL, | |
), | |
5 => | |
array ( | |
0 => 'lynx, catamount', | |
1 => | |
array ( | |
0 => | |
array ( | |
0 => 'common lynx, Lynx lynx', | |
1 => NULL, | |
), | |
1 => | |
array ( | |
0 => 'Canada lynx, Lynx canadensis', | |
1 => NULL, | |
), | |
), | |
), | |
), | |
), | |
), | |
), | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment