如何使用Perl 6类表示嵌套数据结构?

时间:2017-12-02 12:25:16

标签: perl6

上次我不得不处理这些数据时,我使用的是哈希数组,其中每个哈希值都有哈希值等。当循环遍历不同的索引/键时,很难不丢失,所以我认为应该有更好的解决方案。由于我没有OOP经验,我不知道,如何开始...

假设在我们的城市,我们有Library(其内容已被数字化为txt文件),其中包含多个会议室:1_red_room2_blue_room3_white_room。每个房间都有很多书,每bookauthor's_nametitletext(从txt文件中读取)分为pages(与号)。

给定$word,对于每个房间,程序应列出:

room_name, with the overall number of `$word` contexts in all its books
  list of authors, who use this word, with number of contexts
    for every author, list of books, with number of contexts
      for every book, list of pages, with number of contexts

输出示例:

Word: cucumber
TOTAL: 654
1_red_room: 234
  author: John Smith: 70
    title: "In the wild": 3
      page_50:  1
      page_150: 2
    title: "Hello world": 10
      page_1: 2
      page_5: 1
      page_7: 3
...
...
2_blue_room: 114
  author: Wendy Brown
    title: "In the dark": 43
      page_8: 7
...

那么,有没有办法在用户定义的类(或者可能使用其他一些工具)的帮助下处理这些数据?

1 个答案:

答案 0 :(得分:2)

以下是我将如何开始。我会创建一个Book类。然后我会为每个房间创建一个书籍%books的哈希值:

my $total-count = 0;
my @room-info;
for @rooms -> $room {
    my @room-authors;
    my %room-authors;
    my $room-count = 0;
    for @(%books{$room}) -> $book {
        my $count = $book.contains-word( $word );
        if $count > 0 {
            $total-count += $count;
            $room-count += $count;
            my $author = $book.author;
            if %room-authors{$author}:exists {
                $(%room-authors{$author}).update($book, $word, $count);
            }
            else {
                %room-authors{$author} = Room-Author.new(
                    book => $book, word => $word, count => $count
                );
                @room-authors.push( $author );
            }
        }
    }
    if @room-authors.elems > 0 {
        @room-info.push(
            Room-Info.new(
                room => $room, room-count => $room-count,
                order => @room-authors, hash => %room-authors
            )
        );
    }
}
say "Word: $word";
say "TOTAL: $total-count";

for @room-info -> $room {
    my @room-authors = $room.order;
    my %room-authors = $room.hash;
    say $room.room ~ " : " ~ $room.room-count;
    for @room-authors -> $author-str {
        my $author = %room-authors{$author-str};
        say "  author: " ~ $author.name ~ " : " ~ $author.count;
        for @($author.titles) -> $title {
            say "    title: " ~ $title.title ~ " : " ~ $title.count;
            for @($title.pages) -> $page {
                say "      page_" ~ $page.page ~ ": " ~ $page.count;
            }
        }
    }
}

这里的课程PageTitleRoom-InfoBookRoom-Author可能看起来像(注意:更多细节必须填写实际内容)代码):

class Page {
    has Int $.page;
    has Int $.count;
}

class Title {
    has Str $.title;
    has Page @.pages;
    has Int $.count;
}

class Room-Info {
    has $.room;
    has $.room-count;
    has @.order;
    has %.hash;
}

class Book {
    has Str $.author;
    has Str $.title;
    has Str $.text;

    # checks how many times a word occurs in the book
    method contains-word ( $word, --> Int ) {
        return 2;  # Stub, insert more code here..
    }

    method get-page-matches( $word ) {
        return [Page.new(page => 50, count => 1),
                Page.new(page => 150, count => 2)]; # Stub, insert more code..
    }
}

class Room-Author {
    has Title @.titles;
    has Bool %!titles;
    has $.name;
    has $.count;

    submethod BUILD(:$book, :$word, :$!count) {
        my $title = $book.title;
        $!name = $book.author;
        %!titles{$title} = True;
        @!titles.push(
            Title.new(title => $title,
                      pages => $book.get-page-matches( $word ),
                      count => $!count,
                     )
        );
    }
    method update( $book, $word, $count ) {
        my $title = $book.title;
        $!count += $count;
        my $author = $book.author; # should be the same as $.name.. 
        if %!titles{$title}:exists {
            die "Unexpected: Duplicate title '$title' for $author";
        }
        else {
            %!titles{$title} = True;
            my Page @pages = $book.get-page-matches( $word );
            @!titles.push(
                Title.new(title => $title,
                          pages => $book.get-page-matches( $word ),
                          count => $count,
                         ) );
        }
    }
}