6.10.94-stable

Tables

Table is a core GreyCat type, that serves as a generic two-dimensional container. It is typically used to return a result set. For example, web components can handle Table objects returned by the GreyCat backend. Also, the Explorer can display Table objects.

Sampling results can also be expressed as Tables.

Data elements

Tables are populated one cell at a time. Not all cells need to contain values (null in this case).

fn main() {

  var t = Table::new(4);  // creates a table with 4 columns

  t.set(0, 0, 12335);
  t.set(0, 1, "onetwothree...");  // 1st row, 2nd column
  t.set(0, 2, Date::new(2022, 11, 22, 06, 35, 00, 0, TimeZone::Europe_Luxembourg));

  t.set(1, 1, "...threefive");
  t.set(1, 3, time::now());
  // other cells of 2nd row are null

  info(t.rows());  // 2

  t.remove(0, 1);  // removes row 0

  info(t.get(0, 1));  // "...threefive"
  info(t.get(0, 0));  // null
}

A Table can be sorted along one column.

t.sort(1, true);  // sorts by ascending order

Column information

The other essential aspect to Tables are their columns’ meta information. Each column is described by a TableColumnMeta object.

fn main() {
  var t = Table::new(2);
  t.setHeader(0, "N");

  t.set(0, 0, 10);
  t.set(1, 0, 20);

  var meta = t.getMeta(0);
  println(meta);
}

Displays: {"_type":"core.TableColumnMeta","type":"core.int","size":2,"index":false,"header":"N","min":10,"max":20,"avg":15,"std":7}.

use runtime;

fn main() {
  var t = Table::new(2);
  t.setHeader(0, "time");  // label a column

  t.set(0, 0, time::now());
  Runtime::sleep(1_s);  // sleep for 1 second
  t.set(1, 0, time::now());

  var meta = t.getMeta(0);
  println("column '${meta.header}' (${meta.type}): average of ${meta.size} values = ${meta.avg}");
}

Each column’s meta information also includes: min, max values, standard deviation. A column’s type is null whenever there are values of different types (or no values at all).

Looping over a Table

for (var row = 0; row < t.rows(); row++) {
  var col0 = t.get(row, 0);
}

Applying mappings

A Table can be transformed by applying mappings to its columns.

A mapping is a series of extractors to apply to a specific column on a table.

var t = Table::new(3);
var mappings = [
  TableColumnMapping { column: 0, extractors: ["*", "a"] }, // resolve the node get the attribute
  TableColumnMapping { column: 1, extractors: ["a"] }, // resolve the field
  TableColumnMapping { column: 1, extractors: ["c", "d"] }, // resolve the nested field
  TableColumnMapping { column: 2, extractors: [0] } // resolve the offset
];

var nestedObj = {
  d: "nested value"
};

var obj = {
  a: "attribute a",
  c: nestedObj
};

t.set(0, 0, node::new(obj));
t.set(0, 1, obj);
t.set(0, 2, ["array index 0"]);


var newTable = Table::applyMappings(t, mappings);

The new Table wil contain 4 new columns with our specified mappings.

[
  {
    "_type": "core.node",
    "ref": "0440000000000000"
  },
  {
    "a": "attribute a",
    "c": {
      "d": "nested value"
    }
  },
  [
    "array index 0"
  ],
  "attribute a", // resolved from the node
  "attribute a", // resolved from the object
  "nested value", // resolved from the nested object
  "array index 0" // resolved from the array
]

Reference

native type Table<T> {
  /// Returns a new table object, which `cols` columns.
  static native fn new(cols: int): Table<T>;

  /// Returns the meta_data about column `col` of the table.
  native fn getMeta(col: int): TableColumnMeta;

  /// Sets `value` at row `row` and column `col`.
  native fn set(row: int, col: int, value: T);

  /// Returns the value located at row `row` and column `col` of the table.
  native fn get(row: int, col: int): T;

  /// Returns the number of columns of the table.
  native fn cols(): int;

  /// Returns the number of rows of the table. This number is based on the maximum index of a set column in the table, regardless of the skipped indices.
  native fn rows(): int;

  /// Sorts rows of the table by values of column `col`. Sorts by ascending order if `asc` is set to true, sorts by descending order otherwise.
  native fn sort(col: int, asc: bool);

  /// Removes rows which indexes are within the interval `[from, to[`.
  native fn remove(from: int, to: int);

  /// Set a header name to a column.
  native fn setHeader(col: int, name: String);

  /// Produces a new table by applying mappings to columns.
  @expose
  static native fn applyMappings(table: Table, mappings: Array<TableColumnMapping>): Table;
}

type TableColumnMeta {
  type: String?;
  size: int;
  index: bool;
  header: String?;
  min: any?;
  max: any?;
  avg: any?;
  std: any?;
}

/// Describes a series of extractors to apply to a specific column on a table
type TableColumnMapping {
  /// The targetted column offset (zero-based)
  column: int;
  /// A list of extractors to execute sequentially on the targetted `column`'s value:
  ///
  /// | Value    | Extractor | Description                            |
  /// | -------- | --------- | -------------------------------------- |
  /// | `node`   | `"*"`     | Resolve the node (eg. `*n`)            |
  /// | `node`   | `"ident"` | Resolve the field (eg. `n->ident`)     |
  /// | `object` | `"ident"` | Resolve the field (eg. `o.ident`)      |
  /// | `Map`    | `key`     | Resolve the key (eg. `m.get(key)`)     |
  /// | `Array`  | `1`       | Resolve the offset (eg. `a[1]`)        |
  extractors: Array<any>;
}