withRowsOrderedBy method

DataFrame withRowsOrderedBy(
  1. List<String> columns, {
  2. bool decreasing = false,
})

A new data frame with the rows ordered by the values in columns.

Example:

final d = """
  x,y,z
  9,3,bat
  3,6,zebra
  7,4,moose
  3,8,bat
  8,4,zebra
  6,5,bat,
  1,7,zebra
  3,9,moose
""".parseAsCsv();

print(d.withRowsOrderedBy(["z", "x"]));

.-.-.-------.
|x|y|z      |
:-+-+-------:
|3|8|bat    |
|6|5|bat    |
|9|3|bat    |
|3|9|moose  |
|7|4|moose  |
|1|7|zebra  |
|3|6|zebra  |
|8|4|zebra  |
'-'-'-------'

Implementation

DataFrame withRowsOrderedBy(
  List<String> columns, {
  bool decreasing = false,
}) {
  int compareLists(
    List<int> a,
    List<int> b, [
    int index = 0,
  ]) =>
      index == a.length
          ? 0
          : (a[index] > b[index]
              ? 1
              : (a[index] < b[index]
                  ? -1
                  : compareLists(
                      a,
                      b,
                      index + 1,
                    )));

  final orderCriterion = [
        for (var _ = 0; _ < rowNumber; _++)
          [for (var _ = 0; _ < columns.length; _++) 0]
      ],
      uniqueNumeric = {
        for (final MapEntry(:key, :value) in numericColumns.entries)
          key: NumericColumn(value.uniqueValues)
      },
      uniqueNumericIndexOrders = <String, Map<num, int>>{},
      uniqueCategoric = {
        for (final MapEntry(:key, :value) in categoricColumns.entries)
          key: CategoricColumn(value.uniqueValues)
      },
      uniqueCategoricIndexOrders = <String, Map<String, int>>{};

  for (final MapEntry(:key, :value) in uniqueNumeric.entries) {
    final indexOrders = value.indexOrders;
    uniqueNumericIndexOrders[key] = {};
    for (var i = 0; i < value.length; i++) {
      uniqueNumericIndexOrders[key]![value[i]] = indexOrders[i];
    }
  }

  for (final MapEntry(:key, :value) in uniqueCategoric.entries) {
    final indexOrders = value.indexOrders;
    uniqueCategoricIndexOrders[key] = {};
    for (var i = 0; i < value.length; i++) {
      uniqueCategoricIndexOrders[key]![value[i]] = indexOrders[i];
    }
  }

  void updateIndexOrders(List<int> indexOrders, int index) {
    for (var i = 0; i < rowNumber; i++) {
      orderCriterion[i][index] = indexOrders[i];
    }
  }

  for (var i = 0; i < columns.length; i++) {
    final columnName = columns[i];
    if (numericColumns.containsKey(columnName)) {
      updateIndexOrders([
        for (final x in numericColumns[columnName]!.values)
          uniqueNumericIndexOrders[columnName]![x]!
      ], i);
    } else if (categoricColumns.containsKey(columnName)) {
      updateIndexOrders([
        for (final x in categoricColumns[columnName]!.values)
          uniqueCategoricIndexOrders[columnName]![x]!
      ], i);
    } else {
      throw PackhorseError.badColumnName(columnName);
    }
  }

  final orderedIndices = [for (var i = 0; i < rowNumber; i++) i]
    ..sort((a, b) => compareLists(orderCriterion[a], orderCriterion[b]));

  return withRowsAtIndices(orderedIndices);
}