階層の問題
以下の様な文字列を
foo:表示 aa:表示 bb:表示 cc:表示 dd:表示 ee:表示 ff:表示 bar:表示 ff:表示 gg:表示
↓のように変換したい問題
[ { 'value' => 'foo', 'data' => [ { 'value' => 'aa', 'is_show' => 't' }, { 'value' => 'bb', 'is_show' => 't' }, { 'value' => 'cc', 'data' => [ { 'value' => 'dd', 'is_show' => 't' }, { 'value' => 'ee', 'is_show' => 't' }, ], 'is_show' => 't' }, ], 'is_show' => 't', }, { 'value' => 'bar', 'data' => [ { 'value' => 'ff', 'is_show' => 't' }, { 'value' => 'gg', 'is_show' => 't' }, ], 'is_show' => 't', }, ]
以下のようにしてみました。
#!/usr/bin/perl -w use strict; my $text = qq|foo:非表示 aa:表示 bb:非表示 cc:表示 dd:表示 ee:非表示 ff:表示 bar:表示 ff:表示 gg:非表示 hoge:表示 moge:表示|; my $text2 = qq|aaa:表示 bbb:非表示 ccc:表示 ddd:表示 eee:表示|; my @texts = split(/(?:\r\n|\r|\n)/, $text2); # ここに入れていく my $array = ; # 階層 my $level_count = 0; for(my $i=0; $i < scalar @texts; $i++) { # 階層が下がった if($level_count < ($texts[$i] =~ tr/ //)) { # 進んだ回数、親、配列、階層を渡す my $parent = $texts[$i-1]; $level_count++; # 階層が一つ下がった my $child_array; my $is_last; ($i, $child_array, $level_count, $is_last) = &_array($i, $parent, \@texts, $level_count); # $level_count--; # 戻ってきたら一つ階層が上がる my $hash = {}; # 親子のペア my( $value, $is_show ) = ($parent =~ m/[\s+]?([^\s].+):(非表示|表示)/); $hash->{value} = $value; $hash->{is_show} = ($is_show =~ m/^表示$/ ? 't' : 'f'); $hash->{data} = $child_array; # 1階層目のデータ push(@$array, $hash); # 進めた分進める $i = $i - 1; # 最後だったら終わり if( $is_last ) { last; } } else { # 次のデータが一つ下がるなら無視(親子の関係を作るため) next if($texts[$i+1] && ($texts[$i] =~ tr/ //) < ($texts[$i+1] =~ tr/ //)); # 1階層目のデータ my( $value, $is_show ) = ($texts[$i] =~ m/[\s+]?([^\s].+):(非表示|表示)/); push(@$array, {'value' => $value, 'is_show' => ($is_show =~ m/^表示$/ ? 't' : 'f')}); } } use Data::Dumper; die Dumper $array; sub _array { my $num = shift; my $parent = shift; my $texts = shift; my $level_count = shift; # ここに入れていく my $array = ; # 進めた回数 for(my $i=$num; $i < scalar @$texts; $i++) { ## 階層の比較 # 階層が一つ下がった if($level_count < ($texts->[$i] =~ tr/ //)) { my $parent = $texts->[$i-1]; $level_count++; # 階層が一つ下がる my $child_array; my $is_last; ($num, $child_array, $level_count, $is_last) = &_array($i, $parent, $texts, $level_count); # $level_count--; # 戻ってきたら一つ階層が上がる my $hash = {}; # 親子のペア my( $value, $is_show ) = ($parent =~ m/[\s+]?([^\s].+):(非表示|表示)/); $hash->{value} = $value; $hash->{is_show} = ($is_show =~ m/^表示$/ ? 't' : 'f'); $hash->{data} = $child_array; # 同じ階層のデータ push(@$array, $hash); # 進めた分進める $i = $num - 1; # 最後だったら返す if( $is_last ) { return ($#$texts, $array, $level_count, 1); } # 階層が一つ上がった } elsif($level_count > ($texts->[$i] =~ tr/ //)) { $level_count--; # 階層が一つ上がる return ($i, $array, $level_count); # 同じ階層だった } elsif($level_count == ($texts->[$i] =~ tr/ //)) { # 次のデータが一つ下がるのなら無視(親子の関係を作るため) next if($texts->[$i+1] && ($texts->[$i] =~ tr/ //) < ($texts->[$i+1] =~ tr/ //)); # 次のデータも同じ階層か階層が一つ上がる場合は同じ階層のデータとして入れる my( $value, $is_show ) = ($texts->[$i] =~ m/[\s+]?([^\s].+):(非表示|表示)/); push(@$array, {'value' => $value, 'is_show' => ($is_show =~ m/^表示$/ ? 't' : 'f')}); } } ## 最後まで行ってしまったら、そのまま帰す return ($#$texts, $array, $level_count, 1); }
どなたか添削してください。
この後、逆変換もやります。