function _do_reduce($path, $ctx)
 {
     //    my $indent = ' ' x $ctx->{depth};
     $indent = str_repeat(' ', $ctx['depth']);
     //    my $debug  =       $ctx->{debug};
     $debug = $ctx['debug'];
     //    my $ra = Regexp::Assemble->new(chomp=>0);
     $ra = new Regexp_Assemble(array('chomp' => 0));
     //    $ra->debug($debug);
     $ra->__debug = $debug;
     //$ra->__debug = 255;
     //    $debug and print "# $indent| do @{[_dump($path)]}\n";
     if ($debug) {
         echo "# {$indent}| do " . $this->_dump($path) . "\n";
     }
     //    $ra->_insertr( $_ ) for
     //        # When nodes come into the picture, we have to be careful
     //        # about how we insert the paths into the assembly.
     //        # Paths with nodes first, then closest node to front
     //        # then shortest path. Merely because if we can control
     //        # order in which paths containing nodes get inserted,
     //        # then we can make a couple of assumptions that simplify
     //        # the code in _insert_node.
     //        sort {
     //            scalar(grep {ref($_) eq 'HASH'} @$a)
     //            <=> scalar(grep {ref($_) eq 'HASH'} @$b)
     //                ||
     //            _node_offset($b) <=> _node_offset($a)
     //                ||
     //            scalar @$a <=> scalar @$b
     //        }
     //        @$path
     //    ;
     $self = $this;
     //php5.4からは thisは暗黙なのだが・・ php5.3で動かしたいので、一度代入して自分で束縛する.
     $_temp_path = $this->_perl_sort(function ($a, $b) use($self) {
         $scalar_count_a = count($self->_perl_grep(function ($_) {
             return is_array($_);
         }, $a));
         $scalar_count_b = count($self->_perl_grep(function ($_) {
             return is_array($_);
         }, $b));
         if ($scalar_count_a > $scalar_count_b) {
             return 1;
         } else {
             if ($scalar_count_a < $scalar_count_b) {
                 return -1;
             }
         }
         $temp_b = $self->_node_offset($b);
         $temp_a = $self->_node_offset($a);
         if ($temp_b > $temp_a) {
             return 1;
         } else {
             if ($temp_b < $temp_a) {
                 return -1;
             }
         }
         $temp_a = count($a);
         $temp_b = count($b);
         if ($temp_a > $temp_b) {
             return 1;
         } else {
             if ($temp_a < $temp_b) {
                 return -1;
             }
         }
         //挙動を見ていると辞書順な気がする・・・
         return strcmp(is_array($a) ? json_encode($a) : $a, is_array($b) ? json_encode($b) : $b);
         //            return 0;
     }, $path);
     foreach ($_temp_path as $_) {
         $ra->_insertr($_);
     }
     //    $path = $ra->_path;
     $path = $ra->__path;
     //    my $common = [];
     $common = array();
     //    push @$common, shift @$path while( ref($path->[0]) ne 'HASH' );
     //これでいいんかな?
     while (count($path) > 0 && !is_array($path[0])) {
         //        $common = $this->_perl_push2($common, array_shift($path));
         $_temp_node = array_shift($path);
         if (is_array($_temp_node)) {
             $common = array_merge($common, $_temp_node);
         } else {
             $common[] = $_temp_node;
         }
     }
     //    my $tail = scalar( @$path ) > 1 ? [@$path] : $path->[0];
     $tail = count($path) > 1 ? $path : $path[0];
     //    $debug and print "# $indent| _do_reduce common={[_dump($common)]} tail=@{[_dump($tail)]}\n";
     if ($debug) {
         echo "# {$indent}| _do_reduce common=" . $this->_dump($common) . " tail=" . $this->_dump($tail) . "\n";
     }
     //    return ($common, $tail);
     return array($common, $tail);
     //}
 }