daily pastebin goal
21%
SHARE
TWEET

Data::StaticTable Work in progress

a guest Jan 18th, 2018 88 in 28 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. use v6;
  2. use Test;
  3. unit module Data::StaticTable;
  4.  
  5. class X::Data::StaticTable is Exception {
  6.     method not-found { "Not found"; }
  7.     method header-definition { "Invalid header definition"; }
  8.     method message() { "Generic error"; }
  9. }
  10.  
  11. subset Position of Int where 1 .. *;
  12.  
  13. =begin pod
  14.  
  15. StaticTable allows you to handle bidimensional data in a more natural way
  16. Some features:
  17. * Columns and Rows starts at 1
  18. * Columns may have header names
  19. * Any column can work as an index
  20.  
  21. If the number of elements provided does not suffice to form a
  22. sauqre or a rectangle, empty cells will be added.
  23.  
  24. =end pod
  25.  
  26. class Data::StaticTable {
  27.     has Position $.columns;
  28.     has Position $.rows;
  29.     has @!data;
  30.     has Str @.header;
  31.     has %.column;
  32.  
  33.     method perl {
  34.         my Str $out = "Columns:$!columns Rows:$!rows" ~ "\n";
  35.         $out ~= "Header:" ~ @!header.perl ~ "\n" ~ "Columns Index:" ~ %!column.perl ~ "\n" if (@.header.elems != 0);
  36.         $out ~= @!data.perl;
  37.     }
  38.  
  39.     method display {
  40.         my Str $out;
  41.         for (1 .. $!rows) -> $row-num {
  42.             $out ~= "\n";
  43.             for (1 .. $!columns) -> $col-num {
  44.                 my $cell = self!get-cell-by-column($col-num, $row-num).perl;
  45.                 $out ~= "[" ~ $cell ~ "]\t";
  46.             }
  47.         }
  48.         my Str $header;
  49.         $header = join("\t", @.header);
  50.         my Str @u;
  51.         for (@.header) -> $h {
  52.             @u.append("⋯" x $h.chars);
  53.         }
  54.         return $header ~ "\n" ~ join("\t", @u) ~ $out;
  55.     }
  56.  
  57.     submethod BUILD (
  58.     :@!data, :@!header, :%!column, Position :$!columns, Position :$!rows
  59.     ) { }
  60.  
  61.     method !calculate-dimensions(Position $columns, Int $elems) {
  62.         my $extra-cells = $elems % $columns;
  63.         $extra-cells = $columns - $extra-cells if ($extra-cells > 0);
  64.         my @additional-cells = Any xx $extra-cells; #Any objects to fill an incomplete row
  65.         my Position $rows = ($elems + $extra-cells) div $columns;
  66.         return $rows, |@additional-cells;
  67.     }
  68.  
  69.     multi method new(@header!, +@new-data) { #-- It should be Str @header!
  70.         #Die if @header is empty
  71.         die X::Data::StaticTable.header-definition() if (@header.elems < 1);
  72.         my ($rows, @additional-cells) = self!calculate-dimensions(@header.elems, @new-data.elems);
  73.         my Int $col-num = 1;
  74.         my %column-index = ();
  75.         for (@header) -> $header-name {
  76.            %column-index{$header-name} = $col-num++;
  77.         }
  78.         #Die if header has repeated elements
  79.         die X::Data::StaticTable.header-definition() if (@header.elems != %column-index.keys.elems);
  80.         @new-data.append(@additional-cells);
  81.         return self.bless(
  82.             columns => @header.elems,
  83.             rows    => $rows,
  84.             data    => @new-data,
  85.             header  => @header,
  86.             column  => %column-index
  87.         );
  88.     }
  89.     multi method new(Position $columns!, +@new-data) {
  90.         my @header = ('A', 'B' ... *)[0 ... $columns - 1];
  91.         self.new(@header.list, @new-data);
  92.     }
  93.  
  94.     #-- Accessing cells directly
  95.     method !get-cell-by-column(Position $col!, Position $row!) {
  96.         my $pos = ($!columns * ($row-1)) + $col - 1;
  97.         if ($pos >= @!data.elems) {
  98.             die X::Data::StaticTable.not-found();
  99.         }
  100.         return @!data[$pos];
  101.     }
  102.     method get-cell(Str $column-header, $row) {
  103.         my Position $column-number = self!get-column-number($column-header);
  104.         return self!get-cell-by-column($column-number, $row);
  105.     }
  106.  
  107.     #-- Retrieving a column by its name
  108.     method !get-column-number(Str $column-header) {
  109.         if (%!column{$column-header}:exists) {
  110.             return %!column{$column-header};
  111.         }
  112.         die X::Data::StaticTable.not-found();
  113.     }
  114.     method !get-column-by-number(Position $column) {
  115.         my Int $pos = $column - 1;
  116.         return @!data[$pos+($!columns*0), $pos+($!columns*1) ... *];
  117.     }
  118.     method get-column(Str $column-header) {
  119.         my Position $column-number = self!get-column-number($column-header);
  120.         return self!get-column-by-number($column-number);
  121.     }
  122.  
  123.     #-- Retrieving specific rows
  124.     method get-row(Position $row) {
  125.         if (($row < 1) || ($row > $.rows)) {
  126.             die X::Data::StaticTable.not-found();
  127.         }
  128.         return @!data[($row-1) * $!columns ... $row * $!columns - 1];
  129.     }
  130.     method !get-rows(@rownums) {
  131.         my @result = gather for (@rownums) -> $num { take self.get-row($num) };
  132.         return @result;
  133.     }
  134.  
  135.     #-- Shaped arrays
  136.     #-- Perl6 shaped arrays:  @a[3;2] <= 3 rows and 2 columns, starts from 0
  137.     #-- This method returns the data only (not headers)
  138.     method get-shaped-array() {
  139.         my @shaped;
  140.         my @rows = self!get-rows(1 .. $.rows);
  141.         for (1 .. $.rows) -> $r {
  142.             my @row = @rows[$r];
  143.             for (1 .. $.columns) -> $c {
  144.                 @shaped[$r - 1;$c - 1] = self!get-cell-by-column($c, $r);
  145.             }
  146.         }
  147.         return @shaped;
  148.     }
  149.     #==== Positional =====
  150.     multi method elems(::?CLASS:D:) {
  151.         return @!data.elems;
  152.     }
  153.  
  154.     method AT-POS(::?CLASS:D: Position $row) {
  155.         return @.header.list if ($row == 0);
  156.         my @row = self.get-row($row);
  157.         my %full-row;
  158.         for (0 .. $.columns - 1) -> $i {
  159.             %full-row{@.header[$i]} = @row[$i];
  160.         }
  161.         return %full-row;
  162.     }
  163. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top