Last active
December 19, 2017 15:44
-
-
Save denkspuren/5b1a048bce056c478794007a1467377b to your computer and use it in GitHub Desktop.
Thinking about the design of Markdown Excel (to be executed in JShell)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.*; | |
import java.util.function.*; | |
import java.util.stream.*; | |
// This is a design proposal, see https://gist.github.com/denkspuren/c91b4dd9ffcc4c6040ce271e3fd7caa9 | |
class Cell { | |
final int index; | |
final String value; | |
Cell(int index, String value) { | |
this.index = index; | |
this.value = value; | |
} | |
Cell updateValue(Object v) { // { return new Cell(index, v.toString()); } | |
return updateValue(v,"%s"); | |
} | |
Cell updateValue(Object v, String fmt) { | |
return new Cell(index, new Formatter().format(Locale.US,fmt,v).toString()); | |
} | |
public String toString() { return "(" + index + ":" + value + ")"; } | |
static String value(Cell c) { return c.value; } | |
static int index(Cell c) { return c.index; } | |
static ToDoubleFunction<Cell> toDouble = c -> Double.parseDouble(Cell.value(c)); | |
static ToIntFunction<Cell> toInt = c -> Integer.parseInt(Cell.value(c)); | |
static ToLongFunction<Cell> toLong = c -> Long.parseLong(Cell.value(c)); | |
} | |
class Table { | |
static BiPredicate<Table,Cell> col(int col) { | |
return (BiPredicate<Table,Cell>) (t,c) -> | |
c.index % t.cols == (col >= 0 ? 0 : t.cols) + col % t.cols; | |
} | |
static BiPredicate<Table,Cell> row(int row) { | |
return (BiPredicate<Table,Cell>) (t,c) -> | |
c.index / t.cols == (row >= 0 ? 0 : t.rows) + row % t.rows; | |
} | |
static BiPredicate<Table,Cell> col(Cell cell) { | |
return (BiPredicate<Table,Cell>) (t,c) -> | |
c.index % t.cols == cell.index % t.cols; | |
} | |
static BiPredicate<Table,Cell> row(Cell cell) { | |
return (BiPredicate<Table,Cell>) (t,c) -> | |
c.index / t.cols == cell.index / t.cols; | |
} | |
final int rows, cols; | |
final String[] values; | |
Table(int cols, int rows, String... values) { | |
if (values.length != rows * cols) throw new IllegalArgumentException("size doesn't match cols * rows"); | |
if (Arrays.stream(values).anyMatch(s -> s == null)) throw new IllegalArgumentException("table must not have null values"); | |
this.cols = cols; | |
this.rows = rows; | |
this.values = Arrays.copyOf(values, values.length); | |
} | |
Stream<Cell> stream(BiPredicate<Table,Cell> p) { | |
return IntStream.range(0,values.length) | |
.mapToObj(i -> new Cell(i,values[i])) | |
.filter(c -> p.test(this,c)); | |
} | |
Stream<Cell> stream(Predicate<Cell> p) { return stream((t,c) -> p.test(c)); } | |
Stream<Cell> stream() { return stream(c -> true); } | |
Table update(Cell cell) { | |
if (cell.index < 0 || cell.index >= values.length) throw new IllegalArgumentException("cell index is out of bounds"); | |
String[] nvalues = Arrays.copyOf(values, values.length); | |
nvalues[cell.index] = cell.value; | |
return new Table(cols, rows, nvalues); | |
} | |
Table update(Stream<Cell> s) { | |
Collection<Cell> cells = s.collect(Collectors.toList()); | |
Table t = this; | |
for(Cell c : cells) t = t.update(c); | |
return t; | |
} | |
} | |
Table t = new Table( | |
8,5, | |
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Avg", | |
"1.0", "3.0", "4.0", "6.0", "6.0", "6.5", "4.0", "", | |
"2.3", "3.0", "4.0", "3.2", "6.0", "6.0", "4.0", "", | |
"1.0", "3.0", "4.1", "6.0", "6.0", "3.3", "2.0", "", | |
"4.7", "3.0", "4.0", "6.0", "6.0", "6.0", "4.0", "" | |
); | |
BiPredicate<Table,Cell> header = Table.row(0); | |
BiPredicate<Table,Cell> lastCol = Table.col(-1); | |
BiPredicate<Table,Cell> results = lastCol.and(header.negate()); | |
BiPredicate<Table,Cell> data = lastCol.negate().and(header.negate()); | |
Table tResult = t.update( | |
t.stream(results).map(result -> { | |
BiPredicate<Table,Cell> dataRow = data.and(Table.row(result)); | |
double avg = t.stream(dataRow).collect(Collectors.averagingDouble(Cell.toDouble)); | |
return result.updateValue(avg,"%.3f"); | |
}) | |
) | |
/* This is an alternative to compute `avg` | |
double sum = t.stream(dataRow).mapToDouble(Cell.toDouble).sum(); | |
double count = t.stream(dataRow).count(); | |
double avg = sum/count; | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment