我是靠谱客的博主 留胡子白开水,最近开发中收集的这篇文章主要介绍d的按列赋值数组,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原文
对:

byte[3][3] myArr;

可:

myArr[0] = 5;

并有了:

5,5,5
0,0,0
0,0,0

可类似赋值列吗?myArr[][0] = 5没用.
所有的东西,都在内存中且是并排的,示例(类似数组)涵盖了该问题:

import std.stdio;

void main()
{
  int[COL][ROW] sample = [ [ 5, 5, 5 ],
                           [ 0, 0, 0 ],
                           [ 0, 0, 0 ],
                         ];

  auto arrayish = Arrayish!int(ROW, COL);
  assert(arrayish.length == SUM);

  // 复制数组..
  foreach(r; 0..ROW)
  {
    foreach(c; 0..COL)
    {
      arrayish[r, c] = sample[r][c];
    }
  }

  arrayish.print();

  foreach(n; 0..COL)
  {
    //arrayish.columnMajor(n).writeln;/*
    arrayish[n].writeln;//*/
  }

  // 清理并设置..
  arrayish.elements[] = 0;
  foreach(r; 0..ROW) arrayish[r] = 5;
  arrayish.print();
}

struct Arrayish(T) {
  private {
    T[] elements;
    const size_t row, col;
  }

  this(size_t row, size_t col) {
    this.elements = new T[row * col];
    this.row = row;
    this.col = col;
  }

  ref T opIndex(size_t row = 0, size_t col = 0) {
    return elements[row * this.col + col];
  }

  ref T columnMajor(size_t row = 0, size_t col = 0) {
    return elements[col * this.row + row];
  }

  auto length() {
    return row * col;
  }

  void print() {
    foreach(r; 0..row) {
      foreach(c; 0..col)
        this[r, c].write;
      writeln;
    }
  }
} /* 打印:

555
000
000
5
0
0
500
500
500

*/

我突然想到一个想法,它不影响处理器逐页从堆请求内存的速度,但会受到限制.

import std.stdio, std.algorithm, std.range;

enum : size_t {
  ROW = 11,
  COL = 4,
  SUM = ROW * COL
}

void main()
{
  // 4 正短 x 11 正长:
  auto arr = LimitedArray!COL(ROW);

  assert(arr.cell[0].elements.length >= COL);
  assert(arr.length == SUM);

  alias T = typeof(arr.cell[0].elements[0]);

  auto range = iota!T(T.max/2, T.max, 762).array;
  assert(range.length == SUM);

  range.each!((i, T x) => arr[i] = x);/*
  foreach(i, x; range) {
    arr[i] = x;
    writeln(x);
  }//*/
  arr.print;

  // 8 正字节 x 99 正长:
  auto minMaxTest = LimitedArray!8(99);
  auto testLength = minMaxTest.length;

  minMaxTest[0] = ubyte.min + 1;
  minMaxTest[testLength - 1] = ubyte.max;
  minMaxTest.print;
}

template LimitedArray(size_t col)
{
    enum error = "容量错误";
    enum size = (col + 1) >> 1;

    static if(size >= 3)
    {
      alias T = ubyte; // 最小值,但最大列

    } else static if(size == 2)
    {
      alias T = ushort;// 平均数组

    } else static if(size == 1)
    {
      alias T = uint;  // 最大值,但最小列
    }
    enum s = ulong.sizeof/T.sizeof;

    struct LimitedArray
    {
      invariant(uint.sizeof > size, error);
    private {
      union Cell {
        ulong element;
        T[s] elements;
      }
      Cell[] cell;
      const size_t row;
    }

    this(size_t row) {
      this.cell = new Cell[row];
      this.row = cell.length;
    }

    ref T opIndex(size_t i)
    in(i < length, "区间溢出") {
      auto len = cell.length;
      size_t y, x = i % len;y = i / len;
      return cell[x].elements[y];
    }

    auto length() {
      return row * col;
    }

    void print() {
      foreach(i, c; cell) {
        i.writef!"row %2s =>";
        foreach(e; c.elements) e.writef!"%6s";
        writeln(": ", c.element);
      }
    }
  }
}

下面是使用标准库函数的方法:

import std.range: transversal;
import std.algorithm: map, fill;
import std.stdio: writefln;

void main()
{
    byte[3][3] myArr;
    myArr[]
        .map!((ref row) => row[])
        .transversal(0)
        .fill(byte(5));
    writefln("%(%sn%)", myArr[]);
}

这里唯一技巧是调用映射(map),为把行类型字节[3](不是区间类型)改为字节[](这是区间).
一旦完成了,transversal(0)(转置)每行中在0索引处遍历(即,迭代第一列),并用指定值填充设置这些项中每一项.

启用了优化LDC编译起来非常高效,可内联所有区间函数并展开循环:这里

感谢贡献,这样才有比较机会,下面可看到,用union实现的LimitedArray结构快了15~20倍.

import std.stdio, std.algorithm, std.range;
import std.datetime.stopwatch;

enum set {
    COL = 8, ROW = 65535
}

void main()
{
  ubyte[set.COL][set.ROW] sArray;
  auto lArray = LimitedArray!(set.COL)(set.ROW);
  auto ds = [ Duration.zero, Duration.zero ];
  auto sw = StopWatch(AutoStart.yes);

//#line 1
  sArray[].map!((ref row) =>
    row[]).transversal(0).fill(byte.max);
  ds[0] = sw.peek();
//#line 2
  lArray.cell.each!((ref c) =>
            c.elements[0] = byte.max);
  sw.stop();
  /*
  sArray.writefln!"%(%sn%)";
  lArray.print();//*/

  writefln!"#line1 %s μs"(ds[0].total!"usecs");
  ds[1] = sw.peek - ds[0];
  writefln!"#line2 %s μs"(ds[1].total!"usecs");
  "Percent %".writeln(ds[0]/ds[1]);
} /*

  #line1 3362 μs
  #line2 233 μs
  Percent %14

  */

最后

以上就是留胡子白开水为你收集整理的d的按列赋值数组的全部内容,希望文章能够帮你解决d的按列赋值数组所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部