在Scala模板中呈现模型对象列表(矩阵)的"最佳"方式是什么?
public class Column extends Model {
public String columnLabel;
@OneToMany
public List cells;
}
public class Cell extends Model {
public String rowLabel; //index
public BigDecimal value;
}
对于这个问题,对于所有列对象,cells.size()和rowLabel是一致的。控制器返回一个List[Column]给视图。我已经尝试用一个帮助器将列表转换为数组:
@matrix(list: List[Column]):Array = @{
var rowCount = list.head.values.size()
var colCount = list.size()
var m = Array.ofDim[String](rowCount,colCount)
for (i <- 0 to rowCount-1) {
for ( j <- 0 to colCount-1) {
matrix(i)(j) = list(j).cells(i).value.toString();
}
}
return m;
}
,然后在视图中:
<div>
@for(i <- 1 to currentPage.getList.head.values.size()) {
<div class="row">
@for(j <- 1 to currentPage.getList.size()) {
<div class="col-md-1">@matrix(currentPage.getList)(i)(j)</div>
}
</div>
}
</div>
,但这当然只是提取矩阵值,而不是列或行标签。
是否有一些Scala数组的优点,可以在列表的列表中使用?效率是重要的,因为数组大小将是近似的。20列x 2000行。或者让控制器显式返回矩阵行,而不是尝试在视图中转换它们,这是更好的方法吗?
使用for-comprehension而不是命使式循环,它们在Scala中更自然。对于你的任务,有很多方法可以做到这一点,其中之一是这样的:
// transform your data to grid, i.e. Map((row,col) -> value).
// Do this outside the template and pass the result (so that you get the immutable map as a template input)
val toGrid = {
currentPage.getList.map{ col => col.cells.map(cell =>
(cell.rowLabel, col.columnLabel, cell.value)
)}.flatten.map{ case (row, col, value) => ((row,col)->value) }.toMap
}
@rows = @{toGrid.map{ case ((row,col),value) => row }.toSet.toList.sorted}
@columns = @{toGrid.map{ case ((row,col),value) => col }.toSet.toList.sorted}
<div>
@for(row -> rows) {
<div class="row">
@for(col -> columns) {
<div>@toGrid.get(row,col).getOrElse("")</div> //if you might have missing rows/cols
}
</div>
}
</div>
更新。如果,由于某种原因,您不能在模板之外拥有Scala类,那么下面的代码应该执行得更好(假设行或列之间没有空白):
@data = @{currentPage.getList}
@triplets = @{data.map{
col => col.cells.map(cell => (cell.rowLabel,col.columnLabel,cell.value)
)}.flatten
@rows = @{triplets.groupBy(_._1).map{ case (row,cols) =>
(row, cols.map{ case (row,col,value) => (col,value) })
}}
<div>
@for((row,cols) -> rows.sortBy(_._1)) {
<div class="row">
@for((col,value) -> cols.sortBy(_._1)){
<div>@value</div>
}
</div>
}
</div>