如果我有d二维数组,我知道我可以沿行创建1D切片如下:在d切片二维数组
auto one_dim_arr=two_dim_arr[i][0..$]
有一个简单的方法,使沿列的1D片?有人可能会做什么
auto one_dim_arr=two_dim_arr[0..$][j]
会做什么?
如果我有d二维数组,我知道我可以沿行创建1D切片如下:在d切片二维数组
auto one_dim_arr=two_dim_arr[i][0..$]
有一个简单的方法,使沿列的1D片?有人可能会做什么
auto one_dim_arr=two_dim_arr[0..$][j]
会做什么?
下面是该用户创建的类型可能是什么样子:
// Demo
void main()
{
int[3][3] arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
// simple creation
auto middleColumn = verticalSlice(arr, 1);
assert(middleColumn[1] == 5);
// iteratable
foreach (i, v; middleColumn)
assert(v == 2+i*3);
// still a slice - writing will change original array
middleColumn[1] = 17;
assert(arr[1][1] == 17);
// sliceable itself
auto center = middleColumn[1..2];
center[0] = 42;
assert(arr[1][1] == 42);
// get a normal array with .dup
int[] copyOfMiddleColumn = middleColumn.dup;
}
// Implementation
struct StepSlice(T)
{
T* ptr;
size_t length, step;
T opIndex(size_t index)
in { assert(index<length); }
body { return ptr[step*index]; }
void opIndexAssign(T value, size_t index)
in { assert(index<length); }
body { ptr[step*index] = value; }
StepSlice!T opSlice(size_t start, size_t end)
in { assert(start<=end && end<=length); }
body { return StepSlice!T(ptr+start*step, end-start, step); }
int opApply(int delegate(ref T) dg)
{
int result = 0;
for (size_t i=0; i<length; i++)
{
result = dg(ptr[i*step]);
if (result)
break;
}
return result;
}
int opApply(int delegate(ref size_t, ref T) dg)
{
int result = 0;
for (size_t i=0; i<length; i++)
{
result = dg(i, ptr[i*step]);
if (result)
break;
}
return result;
}
T[] dup()
{
T[] result = new T[length];
for (size_t i=0; i<length; i++)
result[i] = ptr[i*step];
return result;
}
}
StepSlice!T verticalSlice(T, size_t W)(T[W][] arr, size_t column)
{
return StepSlice!T(arr[0].ptr+column, arr.length, W);
}
我认为这是缺少范围原语,但仍然是一个很好的起点。
随着std.range.stride
:
import std.range;
// Demo
void main()
{
int[3][3] arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
// simple creation
auto middleColumn = verticalSlice(arr, 1);
assert(middleColumn[1] == 5);
// iteratable
uint i;
foreach (v; middleColumn)
assert(v == 2+(i++)*3);
// still a slice - writing will change original array
middleColumn[1] = 17;
assert(arr[1][1] == 17);
// sliceable itself
auto center = middleColumn[1..2];
center[0] = 42;
assert(arr[1][1] == 42);
// get a normal array with array()
int[] copyOfMiddleColumn = array(middleColumn);
}
// Implementation
auto verticalSlice(T, size_t W)(T[W][] arr, size_t column)
{
T* start = arr[0].ptr+column;
return stride(start[0..W*arr.length], W);
}
不,这是不可能的。为了这个工作,D片需要有一个步骤。可以创建一个类似于切片的自定义类型(例如std.algorithm.map)。
请注意,上面的建议语法可以编译得很好,但是没有你要找的效果。
你是什么意思的“D片需要有一个步骤”?我不太明白。 –
“一步”是什么意思? – Dan
如果您知道如何在内存中表示二维数组以及切片如何工作,您将知道该程序需要知道每行中同一列上的元素之间的距离。这就是我所说的“步骤”。当前D切片具有一个隐含的步骤。 –
如果输入是一个T[][]
(即动态阵列的动态阵列)和要用作输出,可以分配一个新的“外部”阵列相同,并且用内部数组的切片填充它。这将导致O(n)
op,其中正常切片是O(1)
op。编码留给读者作为练习。
@Haunter:在这里有任何帮助吗? – Mehrdad
是啊!我正在寻找那样的东西。 –
大声笑,这是我第一次看到一个被接受的答案被转移到它原来的同一个人身上...... – Mehrdad