mirror of
https://github.com/processing/processing4.git
synced 2026-02-10 00:59:40 +01:00
224 lines
5.3 KiB
Plaintext
224 lines
5.3 KiB
Plaintext
// first line of the file should be the column headers
|
|
// first column should be the row titles
|
|
// all other values are expected to be floats
|
|
// getFloat(0, 0) returns the first data value in the upper lefthand corner
|
|
// files should be saved as "text, tab-delimited"
|
|
// empty rows are ignored
|
|
// extra whitespace is ignored
|
|
|
|
|
|
class FloatTable {
|
|
int rowCount;
|
|
int columnCount;
|
|
float[][] data;
|
|
String[] rowNames;
|
|
String[] columnNames;
|
|
|
|
|
|
FloatTable(String filename) {
|
|
String[] rows = loadStrings(filename);
|
|
|
|
String[] columns = split(rows[0], TAB);
|
|
columnNames = subset(columns, 1); // upper-left corner ignored
|
|
scrubQuotes(columnNames);
|
|
columnCount = columnNames.length;
|
|
|
|
rowNames = new String[rows.length-1];
|
|
data = new float[rows.length-1][];
|
|
|
|
// start reading at row 1, because the first row was only the column headers
|
|
for (int i = 1; i < rows.length; i++) {
|
|
if (trim(rows[i]).length() == 0) {
|
|
continue; // skip empty rows
|
|
}
|
|
if (rows[i].startsWith("#")) {
|
|
continue; // skip comment lines
|
|
}
|
|
|
|
// split the row on the tabs
|
|
String[] pieces = split(rows[i], TAB);
|
|
scrubQuotes(pieces);
|
|
|
|
// copy row title
|
|
rowNames[rowCount] = pieces[0];
|
|
// copy data into the table starting at pieces[1]
|
|
data[rowCount] = parseFloat(subset(pieces, 1));
|
|
|
|
// increment the number of valid rows found so far
|
|
rowCount++;
|
|
}
|
|
// resize the 'data' array as necessary
|
|
data = (float[][]) subset(data, 0, rowCount);
|
|
}
|
|
|
|
|
|
void scrubQuotes(String[] array) {
|
|
for (int i = 0; i < array.length; i++) {
|
|
if (array[i].length() > 2) {
|
|
// remove quotes at start and end, if present
|
|
if (array[i].startsWith("\"") && array[i].endsWith("\"")) {
|
|
array[i] = array[i].substring(1, array[i].length() - 1);
|
|
}
|
|
}
|
|
// make double quotes into single quotes
|
|
array[i] = array[i].replaceAll("\"\"", "\"");
|
|
}
|
|
}
|
|
|
|
|
|
int getRowCount() {
|
|
return rowCount;
|
|
}
|
|
|
|
|
|
String getRowName(int rowIndex) {
|
|
return rowNames[rowIndex];
|
|
}
|
|
|
|
|
|
String[] getRowNames() {
|
|
return rowNames;
|
|
}
|
|
|
|
|
|
// Find a row by its name, returns -1 if no row found.
|
|
// This will return the index of the first row with this name.
|
|
// A more efficient version of this function would put row names
|
|
// into a Hashtable (or HashMap) that would map to an integer for the row.
|
|
int getRowIndex(String name) {
|
|
for (int i = 0; i < rowCount; i++) {
|
|
if (rowNames[i].equals(name)) {
|
|
return i;
|
|
}
|
|
}
|
|
//println("No row named '" + name + "' was found");
|
|
return -1;
|
|
}
|
|
|
|
|
|
// technically, this only returns the number of columns
|
|
// in the very first row (which will be most accurate)
|
|
int getColumnCount() {
|
|
return columnCount;
|
|
}
|
|
|
|
|
|
String getColumnName(int colIndex) {
|
|
return columnNames[colIndex];
|
|
}
|
|
|
|
|
|
String[] getColumnNames() {
|
|
return columnNames;
|
|
}
|
|
|
|
|
|
float getFloat(int rowIndex, int col) {
|
|
// Remove the 'training wheels' section for greater efficiency
|
|
// It's included here to provide more useful error messages
|
|
|
|
// begin training wheels
|
|
if ((rowIndex < 0) || (rowIndex >= data.length)) {
|
|
throw new RuntimeException("There is no row " + rowIndex);
|
|
}
|
|
if ((col < 0) || (col >= data[rowIndex].length)) {
|
|
throw new RuntimeException("Row " + rowIndex + " does not have a column " + col);
|
|
}
|
|
// end training wheels
|
|
|
|
return data[rowIndex][col];
|
|
}
|
|
|
|
|
|
boolean isValid(int row, int col) {
|
|
if (row < 0) return false;
|
|
if (row >= rowCount) return false;
|
|
//if (col >= columnCount) return false;
|
|
if (col >= data[row].length) return false;
|
|
if (col < 0) return false;
|
|
return !Float.isNaN(data[row][col]);
|
|
}
|
|
|
|
|
|
float getColumnMin(int col) {
|
|
float m = Float.MAX_VALUE;
|
|
for (int row = 0; row < rowCount; row++) {
|
|
if (isValid(row, col)) {
|
|
if (data[row][col] < m) {
|
|
m = data[row][col];
|
|
}
|
|
}
|
|
}
|
|
return m;
|
|
}
|
|
|
|
|
|
float getColumnMax(int col) {
|
|
float m = -Float.MAX_VALUE;
|
|
for (int row = 0; row < rowCount; row++) {
|
|
if (isValid(row, col)) {
|
|
if (data[row][col] > m) {
|
|
m = data[row][col];
|
|
}
|
|
}
|
|
}
|
|
return m;
|
|
}
|
|
|
|
|
|
float getRowMin(int row) {
|
|
float m = Float.MAX_VALUE;
|
|
for (int col = 0; col < columnCount; col++) {
|
|
if (isValid(row, col)) {
|
|
if (data[row][col] < m) {
|
|
m = data[row][col];
|
|
}
|
|
}
|
|
}
|
|
return m;
|
|
}
|
|
|
|
|
|
float getRowMax(int row) {
|
|
float m = -Float.MAX_VALUE;
|
|
for (int col = 0; col < columnCount; col++) {
|
|
if (isValid(row, col)) {
|
|
if (data[row][col] > m) {
|
|
m = data[row][col];
|
|
}
|
|
}
|
|
}
|
|
return m;
|
|
}
|
|
|
|
|
|
float getTableMin() {
|
|
float m = Float.MAX_VALUE;
|
|
for (int row = 0; row < rowCount; row++) {
|
|
for (int col = 0; col < columnCount; col++) {
|
|
if (isValid(row, col)) {
|
|
if (data[row][col] < m) {
|
|
m = data[row][col];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return m;
|
|
}
|
|
|
|
|
|
float getTableMax() {
|
|
float m = -Float.MAX_VALUE;
|
|
for (int row = 0; row < rowCount; row++) {
|
|
for (int col = 0; col < columnCount; col++) {
|
|
if (isValid(row, col)) {
|
|
if (data[row][col] > m) {
|
|
m = data[row][col];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return m;
|
|
}
|
|
}
|