2012-04-25 10 views
5

¿Cuál es la forma correcta de leer un archivo de texto en una matriz de líneas? He encontrado lo siguiente en Rosetta Stone:lee un archivo en una matriz de líneas en d

string[] readLines(string filename) { 
    auto f = File(filename); 
    scope(exit) f.close(); 
    string[] lines; 

    foreach (str; f.byLine) { 
    lines ~= str.idup; 
    } 

    return lines; 
} 

pero parece que está haciendo cambiar el tamaño de una matriz por línea, lo cual es bastante ineficiente. Podría hacer un seguimiento del número de líneas de leer y cambiar el tamaño de la matriz mediante el método de duplicación estándar

int i = 0; 
    foreach (str; f.byLine) { 
    if (lines.length <= i + 1) { 
     lines.length = lines.length * 2 + 1; 
    } 
    lines[i] = str.idup; 
    i++; 
    } 
    lines.length = i; 

pero eso es lo suficientemente código repetitivo que tengo que preguntarme si no estoy pasando por alto algo en la biblioteca estándar que ya hace esto por mí.


Editar: dando comentario más la visibilidad de fwend: this article describe en detalle cómo funciona el conjunto asignador, y por qué anexar se maneja de manera eficiente el tiempo de ejecución

Respuesta

4

En realidad, D se duplicará el espacio reservado de la matriz siempre se queda sin espacio, por lo que no es necesario hacerlo a mano. Hay una gran cantidad de información acerca de las matrices de D's here

+1

lo leí, y no decía nada sobre la estrategia de redimensionamiento interno cuando se agrega a una matriz –

+0

Sí, me estaba dando cuenta de eso, pero sé que así es como funciona. Para obtener más detalles, D en realidad asigna memoria en fragmentos de tamaño de potencia de dos, por lo que si la matriz crece más grande que, por ejemplo, 32 bytes, se reasignará a un segmento de 64 bytes. – ricochet1k

+0

bien, gracias, eso es bueno saber –

4

Es probable que obtenga muchas reasignaciones inicialmente, pero a medida que la matriz crezca, su capacidad debería crecer de tal forma que sea menos probable que se asigne con más anexos. Puede imprimir la propiedad de la matriz capacity para ver cómo crece.

Si usted es particularmente preocupado por el rendimiento añadiendo, sin embargo, a continuación, probablemente debería utilizar std.array.Appender, en cuyo caso, el código sería algo como esto:

string[] readLines(string filename) 
{ 
    auto file = File(filename); 
    auto lines = appender!(string[]); 

    foreach(line; file.byLine()) 
     lines.put(to!string(line)); 

    return lines.data; 
} 

Appender está diseñada para hacer más eficiente añadiendo y aprovechará los trucos que pueda para hacer que anexar sea más eficiente que ~= sería por sí mismo.

4

Tal vez esto:

import std.algorithm; 
import std.array; 
import std.file; 

string[] readLines(string input) 
{ 
    Appender!(string[]) result; 
    foreach (line; input.splitter("\n")) 
     result.put(line); 
    return result.data; 
} 

void main() 
{ 
    string input = cast(string)std.file.read("test.d"); 
    string[] lines = readLines(input); 
} 

Debe ser lo suficientemente rápido, ya resultado es sólo la creación de rebanadas de la cadena de entrada cargado previamente y no asignar nuevas matrices (aparte de la asignación de los cortes a sí mismos, OIA el puntero + longitud campos).

Cuestiones relacionadas