D动态数组初始化,stride和索引操作 [英] D dynamic array initialization, stride and the index operation

查看:188
本文介绍了D动态数组初始化,stride和索引操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,这成了有关数组的三重问题



我认为(动态)数组在D中真的很强大,但是下面一直困扰着我while:



在C ++中,我可以轻松地分配一个具有指定值的数组,但是在DI中没有找到一种方法。当然,以下是没有问题的:

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

但是看起来效率不高,因为第一行将以 0 ,而像 a0 一样。可以在D中完成类似于以下的操作?

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






使用时的另一个效率问题strid in 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;
}

当然我是天真的想法,我可以简单地用stride来创建一个新的数组,没有复制它的元素?没有办法这样做在D,对吗?






所以我去和模拟,好像数组是一样大步将返回,并执行 f 作为:

  f(s,3 ); 

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

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

有没有办法改为写get(x )使用索引运算符 get [x] ?这样我可以静态混合/包括striding get 函数,并保持功能的其余部分相似。我会对所采取的方法感兴趣,因为本地结构体不允许访问函数范围变量(为什么不?)。

解决方案

但是它看起来效率不高,因为第一行将使用0进行初始化,而像a0一样初始化。可以在D中进行类似的操作吗?


使用 std.array.uninitializedArray

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







当然我是天真的想法我可以简单地使用stride来创建一个新的数组,而不复制它的元素?在D中没有办法吗?


您的功能 f 有一个 S [] 作为参数,这不同于 stride 返回。解决这个问题的D方法是使你的 f 函数通过使其成为一个模板来接受任何范围:

  void f(Range)(Range s)
{
foreach(item; s)
//使用项
}

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

或者你可以复制数组:

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

但是,如果数组很大,您可能希望避免复制整个数组。







有没有办法使用索引运算符get [x]写入get(x)?这样我可以静态混合/包含striding get函数,并保持功能的其余部分相似。我会对所采取的方法感兴趣,因为本地结构体不允许访问函数范围变量(为什么不?)。


你可以在你自己的结构体中重载索引运算符。

  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;
}

这是(种)实际 stride 功能。我建议您阅读范围


Sorry, this became a 3-fold question regarding arrays

I think (dynamic) arrays are truly powerful in D, but the following has been bothering me for a while:

In C++ I could easily allocate an array with designated values, but in D I haven't found a way to do so. Surely the following is no problem:

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

But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?

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


Another efficiency matter I have when using stride in 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;
}

Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?


So I went and simulated as if the array was as stride would return, and implemented f as:

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) = ...;
    }
}

Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).

解决方案

But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?

Use std.array.uninitializedArray

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


Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?

Your function f has an S[] as an argument, which is different from what stride returns. The D way to solve this is to make your f function accept any range by making it a template:

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

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

Alternatively you can copy the array:

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

But you probably want to avoid copying the entire array if it is large.


Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).

You can overload the indexing operator in your own struct.

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;
}

This is (kind of) the way the actual stride function works. I'd recommend reading up on Ranges.

这篇关于D动态数组初始化,stride和索引操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆