これはより長くなりますが、はるかに読みやすく、より快適なソリューションです。これを使用する必要はありません (おそらく使用したくないでしょう) が、(あなただけでなく) さまざまなアプローチについてさらに学ぶのに役立つ可能性があります。ツリー ノード用の小さなMooクラスを導入します。このクラスは、読み取り可能な並べ替えと文字列化メソッドを使用して、それ自体に再帰的に名前を追加できます。
編集:完全に異なる非常に短い代替案については、他の回答を参照してください。これらは完全に異なるアプローチであり、この回答はすでに十分に長いため、2つの回答に分割しました。;)
ツリークラス
これは基本的に、ネストされた AoHoAoH... 構造にすぎないことに注意してください-少し砂糖が追加されています。;)
# define a tree structure
package Tree;
use Moo; # activates strict && warnings
use List::Util 'first';
# name of this node
has name => (is => 'ro');
# array ref of children
has subs => (is => 'rw', isa => sub { die unless ref shift eq 'ARRAY' });
基本的な準備 (オブジェクトには 1 つのスカラーname
と 1 つの配列 refがありますsubs
) の後、この回答の主要部分である再帰的なadd_deeply
方法に行き着きます。ここから、すべてがデータ構造の再帰的な性質を反映していることに注意してください。
# recursively add to this tree
sub add_deeply {
my ($self, @names) = @_;
my $next_name = shift @names;
# names empty: do nothing
return unless defined $next_name;
# find or create a matching tree
my $subtree = first {$_->name eq $next_name} @{$self->subs};
push @{$self->subs}, $subtree = Tree->new(name => $next_name, subs => [])
unless defined $subtree;
# recurse
$subtree->add_deeply(@names);
}
次の 2 つの方法はそれほど重要ではありません。基本的に、それらは出力をきれいにするためにここにあります:
# sort using node names
sub sort {
my $self = shift;
$_->sort for @{$self->subs}; # sort my children
$self->subs([ sort {$a->name cmp $b->name} @{$self->subs} ]); # sort me
}
# stringification
use overload '""' => \&to_string;
sub to_string {
my $self = shift;
my $prefix = shift // '';
# prepare
my $str = $prefix . '{TREE name: "' . $self->name . '"';
# stringify children
if (@{$self->subs}) {
$str .= ", children: [\n";
$str .= $_->to_string(" $prefix") for @{$self->subs};
$str .= "$prefix]";
}
# done
return $str . "}\n";
}
これを使用する方法
次に簡単な部分です。__DATA__
(ここから)入力を読むだけでadd_deeply
:
# done with the tree structure: now use it
package main;
# parse and add names to a tree
my $tree = Tree->new(name => 'root', subs => []);
foreach my $line (<DATA>) {
chomp $line;
$tree->add_deeply(split /\\/ => $line);
}
# output
$tree->sort;
print $tree;
__DATA__
C:\A
C:\B\C
D:\AB
C:\B\A
C:\B\A\C
出力:
{TREE name: "root", children: [
{TREE name: "C:", children: [
{TREE name: "A"}
{TREE name: "B", children: [
{TREE name: "A", children: [
{TREE name: "C"}
]}
{TREE name: "C"}
]}
]}
{TREE name: "D:", children: [
{TREE name: "AB"}
]}
]}