2011-11-08 23 views
5

Escribir una matriz MxN (M filas, N columnas) a un archivo CSV:Matrix a CSV en Scala

Mi primer intento, en el mapa, funciona, pero crea N referencias a la StringBuffer. También escribe una coma innecesaria al final de cada fila.

def matrix2csv(matrix:List[List[Double]], filename: String) = { 
    val pw = new PrintWriter(filename) 
    val COMMA = "," 

    matrix.map(row => { 
    val sbuf = new StringBuffer 
    row.map(elt => sbuf.append(elt).append(COMMA)) 
    pw.println(sbuf) 
    }) 
    pw.flush 
    pw.close 
} 

Mi segundo intento, utilizando reducir, también funciona, pero se ve torpe:

def matrix2csv(matrix:List[List[Double]], filename: String) = { 
    val pw = new PrintWriter(filename) 
    val COMMA = "," 

    matrix.map(row => { 
    val sbuf = new StringBuffer 
    val last = row.reduce((a,b)=> { 
     sbuf.append(a).append(COMMA) 
     b 
    }) 
    sbuf.append(last) 
    pw.println(sbuf) 
    }) 
    pw.flush 
    pw.close 
} 

Cualquier sugerencia en un enfoque más concisa e idiomático? Gracias.

+0

¿Cómo se obtiene el segundo intento de compilación? En 'sbuf.append (b)', no hay 'b' en el alcance. –

+0

Gracias Ben. Solucionado eso. –

Respuesta

8

Puede obtener la representación de cadena sencilla:

val csvString = matrix.map{ _.mkString(", ") }.mkString("\n") 

Entonces sólo tiene que volcar en un archivo.

Preste atención a las líneas finales (aquí "\ n"), varían según la plataforma.

+0

Gracias, eso es muy conciso e idiomático. –

5

Idiomáticamente, está haciendo un uso indebido de map utilizándolo para realizar operaciones de efecto secundario. Debería usar foreach para esto en su lugar.

Esto es lo que podría parecer si se ha utilizado un foreach y ha sustituido a su StringBuffer repetitivo con una llamada a la mkString método:

def matrix2csv(matrix:List[List[Double]], filename: String) { 
    val pw = new PrintWriter(filename) 
    val COMMA = "," 
    matrix.foreach { row => pw.println(row mkString COMMA) } 
    pw.flush 
    pw.close 
} 

Tenga en cuenta que mkString utiliza un StringBuilder (un no-thread-safe StringBuffer , lo cual está bien aquí).