【问题标题】:How to represent nested data structures using Perl 6 classes?如何使用 Perl 6 类表示嵌套数据结构?
【发布时间】:2017-12-02 12:25:15
【问题描述】:

上次我必须处理此类数据时,我使用了诸如哈希数组之类的东西,其中每个哈希都可以有哈希值等。在遍历不同的索引/键时,很难不迷路,所以我认为应该有更好的解决方案。由于我没有 OOP 方面的经验,我不知道如何开始...

假设在我们的城市,我们有一个 Library(其内容已被数字化为 txt 文件)有几个房间:1_red_room2_blue_room3_white_room。每个房间里都有很多书,每个book有:author'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
...

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

【问题讨论】:

  • 我希望从现在开始几个小时后得到一个答案,除非那时已经有好的答案。 “在遍历不同的索引/键时,很难不迷路”。也许这里有一个熟悉的问题。我认为,如果您链​​接到您尝试过的那种代码的示例,您会发现它往往会让您迷失方向。
  • @raiph 谢谢。最后我完成了我的代码工作,并且我在工作中经常使用它。那里的实际名称不同(结构包括:文本语料库的名称 -> 出处村庄的名称 -> 说话者的名称 -> 文本的名称 -> 句子的数量)。因此,在语料库的循环中,主要数据被放入my Hash @corpus。为了为@corpus 的每个元素形成数据,我使用了my %text = number => $number, speaker => $speaker... 代码(大约 250 行)很难编写和修改,现在(在我让它工作几周后)很难阅读。 :)
  • 嗨 Eugene...foo => $foo 的惯用 DRY 版本是 :$foo,所以你可以写成 my %text = :$number, :$speaker...。你愿意/被允许分享你现有的代码吗?你觉得 Håkon 的代码比你现有的代码更容易阅读还是更难阅读?
  • 谢谢@raiph!我认为 Håkon 的代码更清晰,但是当他解释他的用户定义类的结构时,我将能够完全理解它。我不能在线发布我的代码(这是集体工作的一部分),但我很乐意私下分享(不确定 SO 上是否有 PM)。
  • 尤金,使用gmail.com@用户地址raiph dot mellor。我希望这周有时间消化和回应。

标签: raku


【解决方案1】:

这是我将如何开始的。我会创建一个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,
                         ) );
        }
    }
}

【讨论】:

  • 看起来很优雅!那么您能否就您将使用哪些类/方法说几句话?我看到BookRoom-InfoRoom-Author 类。它们是如何组织的?
  • @EugeneBarsky 当然!我现在将离开电脑一段时间,所以我稍后会回到这个..
  • 谢谢!!不着急。我现在有一个工作程序,但我想在将来制作一个更通用的程序。
  • 非常感谢您的解释!我将探索代码并可能会提出一些新问题。
猜你喜欢
  • 2014-04-27
  • 1970-01-01
  • 2011-09-27
  • 1970-01-01
  • 2021-07-12
  • 2016-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多