NAME
Text::Table::Read::RelationOn::Tiny - Read binary "relation on (over) a set" from a text table.
VERSION
Version v2.3.1
SYNOPSIS
use Text::Table::Read::RelationOn::Tiny;
my $obj = Text::Table::Read::RelationOn::Tiny->new();
my ($matrix, $elems, $ids) = $obj->get('my-table.txt');
DESCRIPTION
Minimum version of perl required to use this module: v5.10.1
.
This module implements a class that reads a binary relation on a set (homogeneous relation, see https://en.wikipedia.org/wiki/Binary_relation#Homogeneous_relation) from a text table.
The table format must look like this:
| x\y | this | that | foo bar |
|---------+------+------+---------|
| this | X | | X |
|---------+------+------+---------|
| that | | | X |
|---------+------+------+---------|
| foo bar | | X | |
|---------+------+------+---------|
Tables are read by method
get
, see below.Only two different table entries are possible, these are
X
and the empty string (this is default and can be changed, see description ofnew
).The entry in the table's upper left corner is simply ignored and may be empty, but you cannot omit the upper left
|
character.The hotizontal rules are optional.
By default, there is not something like a format check for the horizontal rules or the alignment. Any line starting with
|-
is simply ignored, regardless of the other subsequent characters, if any. Also, the|
characters need not to be aligned, and heading spaces are ignored.However, a format check can be enabled by specifying
get
argumentpedantic
with a true value.If you have not specified a base set in the construcor call, the entries (names) in the table header are the element names of the set. Of course, they must be unique. One of these names may be the empty string. Names my contain spaces or punctuation chars. The
|
, of course, cannot be part of a name.The names of the columns (header line) and the rows (first entry of each row) must be unique, but they don't have to appear in the same order. By default, the set of the header names and the set of the row names must be equal, but this can be changed by argument
allow_subset
of methodget
.
METHODS
new
The constructor takes the following optional named arguments:
inc
-
A string. Table entry that flags that the corresponding elements are related.
|
is not allowed, the value must be different from value ofnoinc
. Heading and trailing spaces are removed.Default is "X".
noinc
-
A string. Table entry that flags that the corresponding elements are not related.
|
is not allowed, the value must be different from value ofinc
. Heading and trailing spaces are removed.Default is the empty set.
set
-
If specified, then this must be an array of unique strings specifying the elements of the set for your relation (it may also contain arrays, see below). When the constructor was called with this argument, then method
elems
will return a reference to a copy of it, andelem_ids
will return a hash mapping each element to its array index (otherwise both methods would returnundef
before the first call toget
).Method
get
will check if the elements in the input table are the same as those specified in the array. Furthermore, the indices inmatrix
will always refer to the indices in theelems
array constructed fromset
, andelems
andelem_ids
will always return the same, regardless of the order of rows and columns in the input table.It may happen that there are elements that are identical with respect to the relation and you do not want to write duplicate rows and columns in your table. To cover such a case, it is allowed that entries of
set
are references to array of strings again (another way is using argumenteqs
).Example:
[[qw(a a1 a2 a3)], 'b', [qw(c c1)], 'd']
In this case, the elements you write in your table are
a
,b
,c
, andd
(in case of a subarray the first element is always taken). Methodget
will add corresponding rows and columns fora1
,a2
,a3
, andc1
to the incidence matrix. Methodelems
will return this (the nested arrays are flattened):[qw(a a1 a2 a3 b c c1 d)]
Method
elem_ids
will return:{ 'a' => '0', 'a1' => '1', 'a2' => '2', 'a3' => '3', 'b' => '4', 'c' => '5', 'c1' => '6', 'd' => '7' }
Method
tab_elems
will return:{ a => 0, b => 4, c => 5, d => 7 }
And method
eq_ids
will return:0 => [1, 2, 3], 5 => [6]
eqs
-
This argument takes a reference to an array of array references. It can only be used if argument
set
is specified, too. Ifeqs
is specified, then the array passed viaset
cannot contain arrays again.This constructor call:
Text::Table::Read::RelationOn::Tiny->new(set => [qw(a a1 a2 a3 b c c1 d)], eqs => [[qw(a a1 a2 a3)], [qw(c c1)]]);
produces the same as this (see description of argument
set
):Text::Table::Read::RelationOn::Tiny->new(set => [[qw(a a1 a2 a3)], 'b', [qw(c c1)], 'd']);
However, the benefit of
eqs
is that you can separate the declaration of the base set and the equivalent elements, meaning that you can enforce an order of the elements independent from what elements are equivalent in your relation. ext
-
"External data". If this boolean option is true, then the array referenced by
set
is not copied. Instead, the contructor uses directly the reference you passed byset
andelems
will return this reference. This means, that you must specifyset
if you setext
to true.You can also specify
elem_ids
along withset
andext
. In this case, the constructor first checks this hash for consistency and then uses the data without copying it. See description ofset
for more details about theelem_ids
hash.Restriction: you can't use array references as entries in the
set
array if you setext
to true. However, you can still useeqs
if you want to specify equivalent elements.Default is false.
elem_ids
-
This can only be specified in conjunction with
ext
andset
. See description of argumentset
.
get
The method reads and parses a table. It takes the following named arguments:
src
-
Mandatory. The source from which the table is to be read. May be either a file name, an array reference or a string containing newline characters.
- Argument is an array reference
-
The method treats the array entries as the rows of the table.
- Argument is a string containing newlines
-
The method treats the argument as a string representation of the table and parses it.
- Argument is a string not containing newlines
-
The method treats the argument as a file name and tries to read the table from that file.
allow_subset
-
Optional. Takes a boolean value. If true, then rows and columns need not to be equal and may contain a subset of the relation's base set only. This way you can omit rows and columns not containing any incidences.
Default is false.
pedantic
-
Optional. Takes a boolean value. If true, then some additional table format checks are done:
Each row (incl. the header) must have a trailing
|
character|
characters (and+
characters of row seperators) must be aligned.Row separators are also checked, but they are still optional.
Indentation (if any) must be the same for all table rows.
Default is false.
Note that the method will stop parsing if it recognizes a line containing not any non-white character and will ignore any subsequent lines.
If you did not specify a base set in the constructor call, then get
will create the set from the table. Then, it creates a hash of hashes representing the relation (incidence matrix): each key is an integer which is an index in the element array created before. Each corresponding value is again a hash where the keys are the array indices of the elements being in relation; the values do not matter and are always undef
. This hash will never contain empty subhashes. (you can obtain this hash from the returned list or from method matrix
).
get
will add identical rows and columns to the resulting incidence matrix for elements that have been specified to be equivalent (see description of new
).
Example
This table:
| x\y | norel | | foo | bar |
|-------+-------+------+-----+-----|
| norel | | | | |
|-------+-------+------+-----+-----|
| | | X | X | |
|-------+-------+------+-----+-----|
| foo | | | | X |
|-------+-------+------+-----+-----|
| bar | | | X | |
|-------+-------+------+-----+-----|
will result in this array:
('norel', '', 'foo', 'bar')
this hash:
('norel' => 0, '' => 1, 'foo' => 2, 'bar' => 3)
and in this hash representing the incidence matrix:
1 => {
1 => undef,
2 => undef
},
3 => {
2 => undef
},
2 => {
3 => undef
}
Note that element norel
(id 0), which is not in any relation, does not appear in this hash (it would be 0 => {}
but as said, empty subhashes are not contained).
Return value:
In scalar context, the method returns simply the object.
In list context, the method returns a list containing three references corresponding to the accessor methods matrix
, elems
and elem_ids
: the hash representing the incidence matrix, the element array and the element index (id) hash. Thus, wirting:
my ($matrix, $elems, $elem_ids) = $obj->get($my_input);
is the same as writing
$obj->get($my_input);
my $matrix = $obj->matrix;
my $elems = $obj->elems;
my $elem_ids = $obj->elem_ids;
However, the first variant is shorter and needs only one method call.
inc
Returns the current value of inc
. See description of new
.
noinc
Returns the current value of noinc
. See description of new
.
prespec
Returns 1 (true) if you specified constructor argument set
when calling the constructor, otherwise it returns an empty string (false).
elems [DUP]
Returns a reference to the array of elements (names from the table's header line), or undef
if you did neither call get
for the current object nor specified option set
when calling the constructor. See description of get
and new
.
If optinal scalar argument DUP has a true value, then a reference to a clone of this array is returned. Default is false.
Note: Without passing a true value via DUP this returns a reference to an internal member, so don't change the content in this case!
elem_ids [DUP]
Returns a reference to a hash mapping elements to ids (indices in array returned by elems
), or undef
if you did neither call get
for the current object nor specified argument set
when calling the constructor.
If optinal scalar argument DUP has a true value, then a reference to a clone of this hash is returned. Default is false.
Note: Without passing a true value via DUP this returns a reference to an internal member, so don't change the content in this case!
tab_elems [DUP]
Returns a reference to a hash whose keys are the elements that may appear in the table. If you did not specify equivalent elements (see description of new
), then the contents of this hash is identical with elem_ids
.
If optinal scalar argument DUP has a true value, then a reference to a clone of this hash is returned. Default is false.
Note: Without passing a true value via DUP this returns a reference to an internal member, so don't change the content in this case!
eq_ids [DUP]
Returns a reference to a hash. If you specified equivalent elements (see description of new
), then the keys are the indices (see elem_ids
and elems
) of the representants and each value is an array of indices of the corresponding equivalent elements (without the representant).
If you did not specify equivalent elements, the this method return undef
after the constructor call, but the first call to get
sets it to an empty hash.
If optinal scalar argument DUP has a true value, then a reference to a clone of this hash is returned. Default is false.
Note: Without passing a true value via DUP this returns a reference to an internal member, so don't change the content in this case!
matrix
Returns the incidence matrix (reference to a hash of hashes) produced by the most recent call of get
, or undef
if you did not yet call get
for the current object. See description of get
.
This method takes the following optional named scalar arguments:
bless
-
Boolean. If true, then the matrix is blessed with
Text::Table::Read::RelationOn::Tiny::_Relation_Matrix
Then you can use the matrix as an object having exactly one method namedrelated
. This method again takes two arguments (integers) and check if these are related with respect to the incidencematrix
. Note thatrelated
does not do any parameter check.Example:
my $matrix = $rel_obj->matrix(bless => 1); if ($matrix->related(2, 5)) { # ... }
Default is false.
dup
-
Boolean. If this has a true value, then a reference to a clone of the matrix is returned. Default is false.
Note: Without setting dup to true this returns a reference to an internal member, so don't change the content!
matrix_named
Returns an incidence matrix just as matrix
does, but the keys are the element names rather than their indices. It takes a single optional boolean named argument bless
doing a job corresponding to the bless
argument of matrix
.
Note: Unlike matrix
the matrix returned by matrix_named
is not a data member and thus it is computed everytime you call this method. This also means that you can change the content of the returned matrix without damaging anything.
PITFALLS
Basically, you do not need spaces around the |
separators. This table, for example, is perfectly fine:
|.|a|b|c|
|-+-+-+-|
|c| |X| |
|-+-+-+-|
|b| | | |
|-+-+-+-|
|a| | |X|
However, if you have element names with a dash at the beginning, then you need a space at least after the first |
character. Example:
- WRONG
-
| x\y | this | that |-blah |- | |-------+------+------+--------+-----| | this | X | | X | X | |-------+------+------+--------+-----| | that | | | X | | |-------+------+------+--------+-----| |-blah | | X | | | |-------+------+------+--------+-----| |- | | | | | |-------+------+------+--------+-----|
- RIGHT
-
| x\y | this | that |-blah |- | |-------+------+------+--------+-----| | this | X | | X | X | |-------+------+------+--------+-----| | that | | | X | | |-------+------+------+--------+-----| | -blah | | X | | | |-------+------+------+--------+-----| | - | | | | | |-------+------+------+--------+-----|
AUTHOR
Abdul al Hazred, <451 at gmx.eu>
BUGS
Please report any bugs or feature requests to bug-text-table-read-relationon-tiny at rt.cpan.org
, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Text-Table-Read-RelationOn-Tiny. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Text::Table::Read::RelationOn::Tiny
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
https://rt.cpan.org/NoAuth/Bugs.html?Dist=Text-Table-Read-RelationOn-Tiny
Search CPAN
https://metacpan.org/release/Text-Table-Read-RelationOn-Tiny
GitHub Repository
https://github.com/AAHAZRED/perl-Text-Table-Read-RelationOn-Tiny
LICENSE AND COPYRIGHT
This software is Copyright (c) 2021 by Abdul al Hazred.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)