Pregunta

Lo siento, esto se convirtió en una pregunta de 3 veces sobre las matrices

Creo que las matrices (dinámicas) son realmente poderosas en D, pero lo siguiente me ha estado molestando por un tiempo:

En C ++ podría asignar fácilmente una matriz con valores designados, pero en DI no he encontrado una manera de hacerlo. Seguramente el siguiente no es un problema:

int[] a = new int[N];
a[] = a0;

Pero parece ineficiente, ya que la línea uno se inicializará con 0, y como 2 con a0. ¿Podría algo similar a lo siguiente en D?

int[] a = new int(a0)[N]; // illegal

Otra materia de eficiencia que tengo al usar Stride en std.Range:

import std.stdio;
import std.range;

struct S
{
    int x;

    this(this)
    {
        writeln("copy ", x);
    }
}

void f(S[] s)
{
}

int main()
{
    S[] s = new S[10];
    foreach (i, ref v; s)
    {
        v.x = i;
    }

    f(stride(s, 3)); // error
    return 0;
}

¿Seguramente estaba pensando ingenuo que podría simplemente usar Stride para crear una nueva matriz sin copiar sus elementos? No hay forma de hacerlo en D, ¿verdad?


Así que fui y simulé como si la matriz fuera como regresaría, e implementé f como:

f(s, 3);

void f(S[] s, uint stride)
{
    ref S get(uint i)
    {
        assert (i * stride < s.length);
        return s[i * stride];
    }

    for (uint x ... )
    {
        get(x) = ...;
    }
}

¿Habría una forma de escribir en su lugar Get (x) usando el operador de índice? get[x]? De esta manera podría mezclar estáticamente / incluir el camino get función y mantener el resto de la función similar. Me interesaría el enfoque adoptado, ya que una estructura local no puede acceder a las variables de alcance de la función (¿por qué no?).

¿Fue útil?

Solución

Pero parece ineficiente, ya que la línea uno se inicializará con 0 y como 2 con A0. ¿Podría algo similar a lo siguiente en D?

Usar std.array.uninitializedArray

S[] s = uninitializedArray!(S[])(N);
s[] = a0; 

¿Seguramente estaba pensando ingenuo que podría simplemente usar Stride para crear una nueva matriz sin copiar sus elementos? No hay forma de hacerlo en D, ¿verdad?

Tu función f tiene un S[] Como argumento, que es diferente de lo que stride devoluciones. La forma de resolver esto es hacer tu f Función Aceptar cualquier rango haciéndolo una plantilla:

void f(Range)(Range s)
{
    foreach (item; s)
        // use item
}

S[] s = new S[10];
f(s); // works
f(stride(s, 3)); // works too

Alternativamente, puede copiar la matriz:

f(array(stride(s, 3)));

Pero probablemente desee evitar copiar toda la matriz si es grande.


¿Habría una manera de escribir en su lugar Get (x) usando el operador de índice Get [x]? De esta manera, podría mezclar / incluir estática la función Get Sending y mantener el resto de la función similar. Me interesaría el enfoque adoptado, ya que una estructura local no puede acceder a las variables de alcance de la función (¿por qué no?).

Puede sobrecargar el operador de indexación en su propia estructura.

struct StrideArray
{
    this(S[] s, uint stride) { m_array = s; m_stride = stride; }

    S opIndex(size_t i) { return s[i * m_stride]; }
    void opIndexAssign(size_t i, S value) { s[i * m_stride] = value; }

    private S[] m_array;
    private uint m_stride;
}

Esta es (más o menos) la forma en que el real stride funciona la función. Recomiendo leer Rangos.

Otros consejos

Puede duplicar (crear una copia de) una matriz con .dup (esto también funcionará con cortes) o puede establecer los elementos con el inicializador de la matriz

int[] a=a0.dup;
int[] b=[e1,e2,e3];

Puede hacer que el F genérico (stride () devuelva una estructura sobre la que puede iterar, no una matriz)

void f(Z)(Z s)if(isInputRange!Z){
    foreach(elem;s){
         //...
    }
}

Recuerde que las matrices son esencialmente estructuras con un campo de puntero a algún bloque de memoria y un campo de tamaño

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top