1

在 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 行。还是让控制器显式返回矩阵行而不是尝试在视图中转换它们是更好的方法?

4

1 回答 1

0

使用 for-comprehensions 而不是命令式循环,它们在 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>
于 2014-07-21T15:17:55.087 回答