0
auto getMultidimensionalArrayShape( T )( T array )
{
  static assert( isArray!( T ) );

  // Retrieve the shape of the input array and double check that
  // the arrays from a same dimension have the same length.
  size_t[] shape;
  // ...

  return shape;
}

getMultidimensionalArrayShape( [1, 2, 3] )  //< returns [3]
getMultidimensionalArrayShape( [[1, 2, 3], [4, 5, 6]] )  //< returns [3][2]
// and so on...

天真地,我会以深度优先的方式迭代以检索索引 0 处每个数组的大小,然后我将检查来自同一维度的其他数组的长度是否与我在索引 0 处找到的内容匹配,只是确保一切都是一致的,但我认为必须有更好的方法......有人有想法吗?

4

2 回答 2

2

这需要递归解决方案。

template depthOf(T){
    static if(isIterable!T)
        enum depthOf=1+depthOf!(ForeachType!T);
    else
        enum depthOf=0;
}

immutable(long)[] getMultidimensionalArrayShape(bool verify=true,T)(T array){
    static assert(isArray!T);
    static if(!isArray!(ForeachType!T)){
        return [array.length];
    }else{
        if(0==array.length)
            return [0L].replicate(depthOf!T).idup;
        const elementDimension=array[0].getMultidimensionalArrayShape();
        static if(verify){
            foreach(child;array[1..$]){
                if(child.getMultidimensionalArrayShape()!=elementDimension)
                    throw new Exception("Shape is not uniform");
            }
        }
        return (array.length~elementDimension).idup;
    }
}

实际上,它并不是真正的递归,因为没有函数调用自身(函数调用从同一模板创建的其他函数)。静态递归是一个更好的名字。

于 2012-09-21T19:27:08.227 回答
0

所以这就是我最终写的内容。基本上,在确保它们都相等之后,我正在收集所有具有相同深度级别的数组并检索它们的维度大小。听起来它工作得很好,唯一的事情是我不确定当 depthLevelArrays 的长度等于 0 时该怎么办?它甚至有意义还是我应该抛出一个异常?

import std.stdio;
import std.traits;


void internal( T )( T[] depthLevelArrays, ref size_t[] shape )
{
  if ( depthLevelArrays.length == 0 )
      writeln( "what to do here?" );

  static if ( isArray!( ForeachType!( T ) ) )
  {
    ForeachType!( T )[] children;
    size_t dimensionSize = depthLevelArrays[0].length;
    foreach ( element; depthLevelArrays )
    {
      if ( element.length != dimensionSize )
        throw new Exception( "Shape is not uniform" );

      foreach ( child; element )
        children ~= child;
    }

    internal( children, shape );
  }
  else
  {
    size_t dimensionSize = depthLevelArrays[0].length;
    foreach ( element; depthLevelArrays )
      if ( element.length != dimensionSize )
        throw new Exception( "Shape is not uniform" );
  }

  shape ~= dimensionSize;
}


auto getMultidimensionalArrayShape( T )( T array )
{
  static assert( isArray!( T ) );
  size_t[] shape;
  internal( [array], shape );
  return shape;
}


void main()
{
  immutable auto array1d = [1.0, 2.5, 3.4];
  auto shape1 = getMultidimensionalArrayShape( array1d );
  writeln( "shape1: ", shape1 ); //< [3]

  int[5][2] array2d = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]];
  auto shape2 = getMultidimensionalArrayShape( array2d );
  writeln( "shape2: ", shape2 );  //< [5][2]

  auto shape3 = getMultidimensionalArrayShape(
      [[[1, 2], [3, 4], [5, 6], [7, 8]],
      [[9, 10], [11, 12], [13, 14], [15, 16]],
      [[17, 18], [19, 20], [21, 22], [23, 24]]] );
  writeln( "shape3: ", shape3 ); //< [2][4][3]

  const int[5][4][3][2] array4d;
  auto shape4 = getMultidimensionalArrayShape( array4d );
  writeln( "shape4: ", shape4 ); //< [5][4][3][2]
}
于 2012-09-22T10:25:40.390 回答