class TaskJuggler::TableColumnSorter

This class can rearrange the columns of a table according to a new order determined by an Array of table headers. The table is an Array of table lines. Each line is another Array. The first line of the table is an Array of the headers of the columns.

Attributes

discontinuedColumns[R]

Public Class Methods

new(table) click to toggle source

Register a new table for rearranging.

# File lib/taskjuggler/TableColumnSorter.rb, line 24
def initialize(table)
  @oldTable = table
  @discontinuedColumns = nil
end

Public Instance Methods

sort(newHeaders) click to toggle source

Rearrange the registered table. The old table won't be modified. The method returns a new table (Array of Arrays). newHeaders is an Array that represents the new column headers. The columns that are not in the new header will be the last columns of the new table.

# File lib/taskjuggler/TableColumnSorter.rb, line 33
def sort(newHeaders)
  # Maps old index to new index.
  columnIdxMap = {}
  newHeaderIndex = newHeaders.length
  oldHeaders = @oldTable[0]
  discontinuedHeaders = []
  oldHeaders.length.times do |i|
    if (ni = newHeaders.index(oldHeaders[i]))
      # This old column is still in the new header
      columnIdxMap[i] = ni
    else
      # This old column is no longer contained in the new header. We
      # append it at the end.
      columnIdxMap[i] = newHeaderIndex
      discontinuedHeaders << oldHeaders[i]
      newHeaderIndex += 1
    end
  end

  # We construct a new table from scratch. All values from the old table
  # are copied over. columns in the new table that were not contained in
  # the old table will be filled with nil.
  newTable = []
  @oldTable.length.times do |lineIdx|
    oldLine = @oldTable[lineIdx]
    if lineIdx == 0
      # Insert the new headers. The discontinued ones will be added below.
      newTable[0] = newHeaders
    else
      # Add a line of nils to the new table.
      newTable[lineIdx] = Array.new(newHeaderIndex, nil)
    end

    # Copy the old column to the new position.
    columnIdxMap.each do |oldColIdx, newColIdx|
      newTable[lineIdx][newColIdx] = oldLine[oldColIdx]
    end
  end

  # Now we need to add the new column headers that were not in the old
  # headers.
  #newTable[0] += discontinuedHeaders

  @discontinuedColumns = discontinuedHeaders.length
  newTable
end